MIPS指令集(一)基本操作

目录

计算机硬件的操作数

存储器操作数

常数或立即数操作数

有符号数和无符号数

指令的格式

逻辑操作

决策指令

循环


计算机硬件的操作数

先从一条C语句入手

cpp 复制代码
a = b + c;

将其翻译为MIPS

cpp 复制代码
add a, b, c

其中a,b,c就是这条指令的操作数。表示将b与c的和放入a中。

加法指令只有三个操作数,也就是说只能一次完成两个数相加,下面的指令序列会完成四个数相加

cpp 复制代码
add a, b, c
add a, a, d
add a, a, e

只能一次完成两个数相加体现了硬件简单性的设计原则。下面会知道,使用指令实际上不会写诸如a,b,c之类的字符,而是使用寄存器。

与高级语言不同,MIPS的算术运算被要求操作数只能来自寄存器。寄存器是构成计算机的基本单元。在MIPS体系结构中寄存器大小为32位,同时拥有32个寄存器。在MIPS体系结构中也常把32位称作一个(word)。

MIPS在使用寄存器时,用''后跟两个字符表示寄存器。用s0,s1...表示类似C语言中的变量所对应的寄存器,用t0,$t1...表示临时变量对应的寄存器。

cpp 复制代码
a = (b + c) - (d + e)

以该C赋值语句为例,将其翻译为MIPS指令,假设s0,...s4分别对应存储了a,..e

cpp 复制代码
add $t0, $s1, $s2 #b+c的结果存在临时变量寄存器t0中
add $t1, $s3, $s4 #同上
add $s0, $t0, $t1

MIPS中#后是注释,注意这种语言一行只有一条指令,且注释是在一行的末尾结束

存储器操作数

高级语言中常有数组和结构体,而且往往大小不止一个字,这种数据结构就会存储在内存中,而内存就是存储器,磁盘更习惯叫做io设备。

由于MIPS算术指令只能操作寄存器,因此必须有一种手段,能将内存中的数据加载到寄存器中。

这些指令叫做数据传输指令

为了访问内存中的字,必须给出地址。内存中的地址是按字节编排的,也就是说每个相邻的地址相差1

图中每一块大小一个字节。

将数据从内存加载到寄存器通常称为取数(load)指令,实际MIPS取数指令助记符是lw,操作数有三个,第一个表示要把数据存到哪个寄存器,第二个是地址偏移量 (单位为字节,要求是常数),第三个是基址寄存器

cpp 复制代码
a = b + A[8];

假设a存在s0,b存在s1,A地址存在s2。

cpp 复制代码
lw $t0, 32($s2) #一个字大小为32位,也就是4字节,8个字就得偏移32字节
add $s0, $s1, $t0

MIPS字的起始地址是4的倍数,这叫做对齐限制。字在内存中如图存储。

MIPS还有一类指令是将寄存器中的数据复制到存储器中,叫做存数(store)指令。MIPS记作sw,用法与lw类似,只是第一个操作数代表要从哪个寄存器中得到数据。

常数或立即数操作数

仅仅从已经介绍的指令来看,要使用常数,只能从存储器取出(lw),如要将a+4

cpp 复制代码
lw $t0, AddrConstant($s1)#AddrConstant为某一常数偏移量,将4加载到t0
add $s0, $s0, $t0

如果要避免使用取数指令,可使用addi指令

cpp 复制代码
addi $s0, $s0, 4

像这种加法叫加立即数(add immediate),常数操作数出现频率高,像这种带立即数的指令,比从存储器种取值快很多,能耗也较低。

常数0可简化指令集。例如,数据传输指令可视为操作数为0的加法。MIPS将$zero恒置为0,编号也为0

有符号数和无符号数

有符号数在MIPS中用补码表示。需要注意的是,当不满32位的数被存储时,高位会补上符号位。

像0100,存在寄存器中

cpp 复制代码
00000000 00000000 00000000 00000100

1100,存在寄存器中

cpp 复制代码
11111111 11111111 11111111 11111100

MIPS有一些末尾为u的指令操作无符号数,具体后面可以见到。

指令的格式

指令以二进制的形式存储,现在我们可以把指令翻译成二进制。

所有的寄存器会被映射为数字,s0\~s7映射到16~23, t0\~t7映射到8~15。

cpp 复制代码
add $t0, $s1, $s2

以该指令为例,先将其翻译为十进制,再转为二进制。

机器指令分为多个字段,本例第一个和最后一个告诉MIPS计算机要执行加法操作,第二个和第三个表示源操作数寄存器,第四个字段表示存放结果的寄存器,第五个字段没有用到,故置为0。

截取《计算机组成与设计 硬件/软件接口》中相关说明

这种指令格式在某些场景可能不适用,如lw指令需要传入偏移量,5位是不够用的,这时,想要增加位数,但是MIPS的设计是,所有指令的长度都相同,这样,就会采取折中方案:所有指令长度相同,但不同类型指令采用不同指令格式。如上述指令就是R型。另一种是I型,用于传输立即数。

在这种I型格式中,立即数大小仍然有限制。可以看到这种格式下,很难增加寄存器的数量,因为寄存器序号会使得rs,rt字段增加位。

逻辑操作

一张图即可解决,用法也与其他指令类似。

决策指令

计算机的运算能力强大,但计算机与计算器的差别在于计算机能执行决策指令,也就是条件分支指令。MIPS有两条类似C语言 if和 go to的指令

cpp 复制代码
beq regsiter1, register2, L1

表示若寄存器register1 和register2的值相等,跳转到L1标签。beq(branch if equal),相等则分支。

cpp 复制代码
bne regsiter1, register2, L1

表示若寄存器register1 和register2的值不等,跳转到L1标签。bne(branch if not equal),不等则分支。

还需介绍另一种分支指令------无条件分支

cpp 复制代码
j L1

j为jump的缩写

cpp 复制代码
if (i == j) 
    f = g + h;
else
    f = g - h;

现在将该C语句编译为MIPS指令。

假设i存在s0,j存在s1,f,g,h分别存在s2,s3,s4

cpp 复制代码
bne $s0, $s1, Else
add $s2, $s3, $s4
j Exit
Else: sub $s2, $s3, $s4
Exit:

循环

条件分支指令可以实现循环

cpp 复制代码
while (save[i] == k)
    i += 1;

假设i和k存在s3和s5中,save的基址存在s6中。

cpp 复制代码
Loop: sll $t1, $s3, 2 #需要将i×4
add $t1, $s6, $t1
lw $t0, 0($t1)        #要求偏移量为常数
bne $t0, $s5, Exit
addi $s3, $s3, 1
j Loop
Exit:
相关推荐
我在人间贩卖青春6 天前
汇编之伪指令
汇编·伪指令
我在人间贩卖青春7 天前
汇编之伪操作
汇编·伪操作
济6177 天前
FreeRTOS基础--堆栈概念与汇编指令实战解析
汇编·嵌入式·freertos
myloveasuka7 天前
汇编TEST指令
汇编
我在人间贩卖青春7 天前
汇编编程驱动LED
汇编·点亮led
我在人间贩卖青春7 天前
汇编和C编程相互调用
汇编·混合编程
myloveasuka8 天前
寻址方式笔记
汇编·笔记·计算机组成原理
请输入蚊子8 天前
《操作系统真象还原》 第六章 完善内核
linux·汇编·操作系统·bochs·操作系统真像还原
myloveasuka8 天前
指令格式举例
汇编·笔记·计算机组成原理
我在人间贩卖青春9 天前
汇编之分支跳转指令
汇编·arm·分支跳转