mips体系结构下的汇编指令
指令集是存储在CPU内部,对CPU运算进行指导和优化的硬程序。拥有这些指令集,CPU就可以更高效地运行。
Mips汇编语言的风格
汇编语言指令格式
[标签:] 操作符 [操作数] [#注释]
| |
xxx:—— 定义代码的人口点和命名数据段的存储段
程序结构
汇编语言的程序结构,为数据声明+代码段+数据段(文件后缀为.s,或者.asm也行),数据声明在代码段之后(其实在其之前也没啥问题,也更符合高级程序设计的习惯)
数据声明
数据段以 .data为开始标志
声明变量后,即在主存(RAM)中分配空间。
| |
代码段:
- 代码段以 .text为开始标志
- 其实就是各项指令操作
- 程序入口为main:标志(这个都一样啦)
- 程序结束标志(详见下文)
其他:
- .data //数据段
- .text //代码段
- .globl //全局符号声明
- .align 0 //关闭所有的自动对齐
- .asciiz //字符串(带终止符)
寄存器
32个通用寄存器:
MIPS的寄存器约定,一种32个寄存器
0 zero: 总返回0
1 at: (汇编暂存寄存器)为汇编保留
2-3 v0、v1:存放子函数调用返回结果,还可用于表达式求值
4-7 a0 - a3:存放向子函数传递的参数
8-15 t0- t7:存放临时运算结果,在发生函数调用时不必保存它们的内容
24,25 t8-t9:
16-23 s0 - s7:存放局部变量,在发生函数调用时一般要保存它们的内容
26,27 k0, k1:为中断/陷入处理保留,你也可以改变
28 gp:全局指针
29 sp: 栈(stack)指针
30 s8/fp: 帧(frame)指针
31 ra: 返回地址(用于过程调用
数据类型
MIPS CPU的一次操作可加载或存储1到8个字节的数据。
MIPS名称
大小(字节)
汇编器助记符
dword | 8 | “d”代表ld | |
word | 4 | “w”代表lw | |
halfword | 2 | “h”代表lh | |
byte | 1 | “b”代表lb | ` |
操作指令
加载和存储(load、store)
Load
在一个内存地址加载word/halfword/byte的数据到一个寄存器
lw r, a | R<-a |
lh r, a | 有符号 |
lb r, a | 有符号 |
lhu | 无符号 |
lbu | 无符号 |
li r,c | 加载立即数 |
Store
将寄存器中的数据存储到内存地址
Sw r, a | R->a |
Sh r, a | Store low halfword |
Sb r, a | Store low byte |
Move:
寄存器之间数据的直接交换
move r , s | R<-s |
逻辑运算
and r, s, t | R <-s . t |
or r, s, t | R <-s + t |
not r, s | R <-s取反 |
xor r, s, t | R <-s异或t |
nor r, s, t | R <-(s+t)再取反 |
算数运算
add r, s, t | R->s + t |
sub r, s, t | R->s – t |
mul r, s, t | R->s*t |
div r, s, t | R->s/t |
- hi和lo乘法器相关的寄存器规模结果接口,不能用于乘和除之外的操作。对于以上二者,不存在直接寻址;必须要通过mfhi(“move from hi”)以及mflo(“move from lo”)两条指令分别来进行访问对应的内容。
- 乘法——将两个整数的相乘结果分成两部分存储的指定的寄存器里。
- 除法——lo寄存器存储结果(商),hi寄存器存储余数。
移位操作
sll r, s, c | r ← shift s left c bits |
srl r, s, c | r ← shift s right c bits |
分支操作
通过条件判断,使程序跳转到tag
b tag | 跳转->tag |
beq r, s, tag | R=s ->tag |
bne r, s, tag | R != s->tag |
bgt r, s, tag | R > s->tag |
bge r, s, tag | R >=s->tag |
blt r, s, tag | R < s->tag |
ble r, s, tag | R<=s->tag |
比较指令
slt r, s, t | S < t |
sle r, s, t | S <= t |
sgt r, s, t | S >t |
sge r, s, t | S >= t |
seq r, s, t | S = t |
sne r, s, t | S != t |
- FALSE r <- 0
- TRUE r <- 1
寻址方式
直接寻址:
MIPS只有一种寻址方式。任何加载或存储机器指令可以写成
lw $1, offset($2)
你可以使用任何寄存器来作为目标和源寄存器。offset偏移量是一个有符号的16位
的数字(因此可以是在-32768与32767之间的任何一值)。用来加载的程序地址是源寄
存器与偏移量的和所构成的地址。
($t0) —— 默认从0地址偏移$t0字节
访问连续的内存空间:
根据程序的实际需要可能进行字符串等数据的访问。
- .ascii s ASCII encoded characters of string s
- .asciiz s l ike .ascii, null-terminated
- .word w1, w2,… 32-bit words w1, w2, . . .
- .half h 1, h 2, . . . 16-bit halfwords h 1, h 2, . . .
- .byte b1, b2, . . . 8-bit bytes b1, b2, . . .
- .float f1, f2, . . . 32-bit single precision floating point numbers f1, f2, . . .
- .double d1, d2, . . . 64-bit double precision floating point numbers d1, d2, . . .
- .space n n zero bytes
例如:1 2
.data str: .asciiz "hello word"
系统调用:syscall
MIPS 提供一条特殊的 syscall 指令,从操作系统获取服务
使用 syscall 系统服务
从 $v0寄存器中读取服务数
从 $a0, $a1, 等寄存器中读取参数值(如果有)
发送 syscall 指令
从结果寄存器中取回返回值(如果有)
$v0 中包含调用号(共12个):
Service | $v0 | Arguments / Result |
Print Integer | 1 | $a0 = integer value to print |
Print Float | 2 | $f12 = float value to print |
Print Double | 3 | $f12 = double vlaue to print |
print String | 4 | $a0 = address of null-terminated string |
Read Integer | 5 | $v0 = integer read |
Read Float | 6 | $f0 = float read |
Read Double | 7 | $f0 = double read |
Read String | 8 | $a0 = address of input buffer$a1 = maximum number of characters to read |
Exit Program | 10 | |
Print Char | 11 | $a0 = character to print |
Read Char | 12 | $a0 = character read |
程序调用
jal a | (jump and link)将程序跳转到地址a并将下一条指令的地址存储在$ra寄存器中 |
j $ra | 返回到程序跳转时的位置,无条件跳转 |