这是我在上完浙大刘鹏老师的视频课后做的笔记。我觉得在学完后,自己写出来会记忆会更深刻,因为要重新梳理一遍。同时遇到不会的还可以重新复习以前的知识。
程序执行流程:
高级语言->汇编语言->逻辑块->数字电路
常用汇编语言:
1.算数指令和访存指令
在汇编语言里面,操作对象是寄存器,而不是高级语言的变量。在RSIC-V里只有32位的32个寄存器,当然也有64位的未来也会有128位的,这里用32 位的。32个寄存器分别命名为x0-x31。不同于高级语言先定义在使用,汇编语言不用定义。但是由于寄存器数量少,所以要从存储器里面加载。在RSIC-V存储系统中,是按照字节为单位来进行寻址的,其中每个字节可以拆分为4个字节大小。在小端系统里,某个字的地址与它最低位字节地址相同,这是因为不大。同时在存储器中存储顺序有大端和小端两种方式,大端是将一个字数据最低位字节存储在最高位字节地址上。小端相反,我国用大端。命令:
按字:
lw(load word)
eg:lw x10,12(x15)#注释符是#,这句表示将从保存在x15的地址上偏移12字节的数据加载到x10寄存器里
sw(store word)
sw x10,12(x15)#把x10的数据加载到保存在x15的地址上偏移12字节的字节上。
按字节(格式与按字指令一样,只针对一字节的数据):
lb(load byte)将字节地址中的1字节数据符号扩展后转载到对应寄存器中(符号扩展,将最高位扩展到其它位)
sb(store byte)将寄存器中最低字节位的1字节数据保存到对应字节地址中
把数据加载到寄存器里面,下面是算法指令:
add eg:add x1,x2,x3#把x2和x3里面的值加起来存到x1
sub 减法,格式和add一样
立即数操作:
addi和add格式一样,没有立即数减法。
2.条件判断分支转移指令
实现条件语句类似的作用。
条件判断分支转移指令:
beq: beq x1,x2,l1#如果x1和x2相等,跳到l1标志符的指令地址空间继续执行指令。不等顺序执行下面的语句
bne:与beq相反,相等执行下面的语句,不等跳到别的状态。
blt:小于号,格式相同
bge:大于号格式相同
无条件分支转移指令:jump(j)
j加标识符,可以直接跳到标识符的指令目标地址
3.逻辑运算指令
都是按位有and(掩码),or,xor,没有逻辑非,逻辑非的实现是使用xor(异或),与0x1111-1111异或即可得到逻辑非
有两种:寄存器型
and x1,x2,x3#x1=x2&x3
立即数
and x1,x2,3#x1=x2&3
移位:
逻辑移位:寄存器型和立即数型
sll(shift left logical):左移,低位补零
slli
slli x1,x2,2#x1=x2<<2
srl:右移,高位补零
srli
算数移位(shift right arithmetic)右移:
sra:右移后空出的高位由原数最高比特位符号扩展得到,格式一样的
srai:
4.函数调用
rsicv里面寄存器的别称。
x1 (通常称为 ra ):返回地址寄存器,用于存储函数调用后的返回地址。
x2 (通常称为 sp ):栈指针,指向栈顶,用于管理栈内存。
x3 (通常称为 gp ):全局指针,用于访问静态数据区域。
x4 - x7 :临时寄存器,可在函数调用中用于保存临时值或局部变量。
x8 (通常称为 tp ):线程指针,用于多线程环境。
x8-x9:s0和s1,x18~x27对应s2~s11,用来保存原进程中的关键数据,避免在函数调用的过程里被破坏。
x10 - x17 :(a0-a7)被调用者保存寄存器,函数调用时被调用者负责保存这些寄存器的值用来传递参数,a0和a1常用来传递返回值。
x28 - x31 :保留寄存器,具体用途取决于特定的实现或应用。
指令大小为四个字节。在程序顺序执行时,在调用后要返回源代码的下一行,所以在调用前先把下一行代码所在的地址保存在ra寄存器里面,当调用完毕后,再用jr ra命令返回之前的代码位置。
jr指令:可以跳转到寄存器所对应的地址空间,用这条指令来实现函数的返回。可以用ret来取代jr ra的操作。
伪指令:mv rd,rs=addi rd,rs,0
li rd,13=addi rd,x0,13
5.栈的使用
在讲这部分前先复习一下栈;
栈:限定在仅在表尾进行插入或者删除的线性表。表尾是栈顶,表头是栈低。是后入先出的线性表(last in first out ,LIFO结构)
顺序栈:初始化时一般不限定大小,后面空间不够时,再加。栈底和栈顶相等时为空栈,插入新的栈顶元素,栈顶加一,删除减一,所以非空栈的栈顶指针一直在下一个元素上。图示为c语言下栈的一些操作。
现在来看栈的使用,当使用寄存器时,调用前可能里面也保存了一些值,为了还原,需要将它保存在栈里面,栈也是存储器的一部分,需要以后指向它的寄存器来保存它的基地址(sp)。函数调用中保存的数据是按照一定顺序组织在一起的,这种组织结构称之为栈帧包括局部变量等等。