常见寄存器
寄存器名 |
别名 |
功能 |
备注 |
x0 |
|
硬连线接0 |
任何对x0的写入操作都无效,x0的值恒定为0,可以用作一个固定的零值,从而简化某些指令的实现 |
x1 |
ra |
返回地址 |
return address |
x2 |
sp |
栈指针 |
栈指针始终指向栈顶 |
x3 |
gp |
全局指针 |
一般用不到,指向全局变量和静态变量 |
x4 |
略 |
线程指针 |
略 |
x5-x7,x28-x31 |
t0-t6 |
临时寄存器 |
temporary的首字母 t , 共有7个 |
x8-x9, x18-x27 |
s0-s11 |
保存寄存器 |
saved 的首字母 s, 共有11个 |
x10-x17 |
a0-a7 |
参数寄存器 |
arg 的首字母a,共有8个.a0a1作为返回值寄存器 |
x8 |
fp |
帧指针/栈基指针 |
使用时需要用栈指针初始化,默认情况下不使用 |
pc |
|
程序计数器指针 |
指向下一条运行的指令 |
汇编
算术指令
指令 |
实例 |
含义 |
备注 |
add |
add t<sub>0</sub>, t<sub>1</sub>, t<sub>2</sub> |
t<sub>0</sub> = t<sub>1</sub> + t<sub>2</sub> |
将t1+t2的值赋值给t0 |
sub |
sub t<sub>1</sub>, t<sub>2</sub>, t<sub>3</sub> |
t<sub>1</sub> = t<sub>2</sub> + t<sub>3</sub> |
将t1-t2的值赋值给t0 |
addi |
addi t<sub>0</sub>, t<sub>1</sub>, -<sub>2</sub> |
t<sub>0</sub> = t<sub>1</sub> + (-2) |
将t1-2的值赋值给t0 |
addi指令:立即数 immediate ,取首字母i。后续从寄存器扩展到立即数的指令都是这样的,在指令的最后加上i。
访存运算
指令 |
实例 |
含义 |
备注 |
ld |
ld t0, 0(t1) |
t0 = memory[t1 + 0] |
将t1的值加上0,将这个值作为地址,取出这个地址所对应的内存中的值,将这个值赋值给t0 |
lw |
lw t2, 20(t3) |
t2 = memory[20 + t3] |
lw 与 ld 的区别就在于 ld 是从内存取出64位数值,而lw是取出32位数值。 |
lh |
lh t4, 30(t5) |
t4 = memory[30 + t5] |
从内存中取出16位数值 |
lb |
lb t4, 30(t5) |
t4 = memory[30 + t5] |
从内存中取出8位数值 |
sd |
sd t0, 0(t1) |
memory[0+t1] = t0 |
将t1的值加上0,将这个值作为地址,将t0的值存储到上述地址所对应的内存中去 |
sw |
sw t0, 0(t1) |
memory[0+t1] = t0 |
与sd的区别在于sw只会将t0的低32位数值存储到相应的内存。sd会将t0的64位都存入 |
sh |
sh t0, 0(t1) |
memory[0+t1] = t0 |
只将t0的低16位所对应的数值存入,也就是一个half word大小 |
sb |
sb t0, 0(t1) |
memory[0+t1] = t0 |
只存入8位,一个byte大小 |
lwu |
lwu t2, 20(t3) |
t2 = memory[20 + t3] |
lw 与lwu的区别在于,前者取出32位数值作符号扩展到64位,而后者做无符号扩展到64位 |
lhu |
lhu t4, 30(t5) |
t4 = memory[30 + t5] |
略 |
lbu |
lbu t4, 30(t5) |
t4 = memory[30 + t5] |
略 |
逻辑指令
指令 |
实例 |
含义 |
备注 |
and |
and t1, t2, t3 |
t1 = t2 & t3 |
按位与,不是 && |
or |
or t1, t2, t3 |
t1 = t2 | t3 |
按位或 |
xor |
xor t1, t2, t3 |
t1 = t2 ^ t3 |
按位异或 |
andi |
andi t1, t2, 4 |
t1 = t2 & 4 |
1&1 = 1 , 1&0 = 0 , 0&0 = 0 |
ori |
ori t1, t2, 4 |
t1 = t2 | 4 |
只有 0|0=0 , 其他结果为 1 |
xori |
xori t1, t2, 4 |
t1 = t2 ^ 4 |
a^0 = a , a^1 = ~a , xor 0 不变,xor 1 切换 |
移位指令
指令 |
实例 |
含义 |
备注 |
sll |
sll t1, t2, t3 |
t1 = t2 << t3 |
t2左移t3位后赋值给t1 |
srl |
srl t1, t2, t3 |
t1 = t2 >>> t3 |
t2右移t3位,做无符号扩展后赋值给t1 |
sra |
sra t1, t2, t3 |
t1 = t2 >> t3 |
t2右移t3位,做符号扩展后赋值给t1 |
slli |
slli t1, t2, 4 |
t1 = t2 << 4 |
t2左移4位后赋值给t1 |
srli |
srli t1, t2, 4 |
t1 = t2 >>> 4 |
t2右移4位,做无符号扩展后赋值给t1 |
srai |
srai t1, t2, 4 |
t1 = t2 >> 4 |
t2右移4位,做符号扩展后赋值给t1 |
分支指令
指令 |
实例 |
含义 |
备注 |
beq |
beq a1, a2, lable |
if(a1 == a2){goto lable;} |
lable是任意自定义的标签 |
bne |
bne a1, a2, lable |
if(a1 != a2){goto lable;} |
|
blt |
blt a1, a2, lable |
if(a1 < a2){goto lable;} |
|
bgt |
bgt a1, a2, 100 |
if(a1 > a2){goto lable;} |
100表示跳转到 pc+100 * 2 的位置 |
bge |
bge a1, a2, 100 |
if(a1 <= a2){goto lable;} |
100与lable对应着相同的指令,实际上在运行时lable会变成pc+xxx |
ble |
ble a1, a2, 100 |
if(a1 >= a2){goto lable;} |
|
跳转指令
指令 |
实例 |
含义 |
备注 |
jal |
jal ra, Symbol |
跳转到Symbol中去,并把ra设置成返回地址 |
Symbol可以是自定义的lable,也可以是某个函数名 |
jal |
jal ra, 100 |
跳转到pc + 100 * 2(指令是定长的)的地方中去,并把ra设置成返回地址 |
pc相对寻址,对应的是位置无关代码(PIC) |
jalr |
jalr ra, 40(t0) |
跳转到t0+40 的地方中去,并把ra设置成返回地址 |
t0+40必须是绝对地址,指向内存中某个确定的地方(往往是函数的开头,并非PIC) |