本文是RVSC-V处理器学习的第一篇文章,对RV32IMAFDC指令集的学习笔记。
1. 运算指令 立即数运算指令addi rd,rs1,imm[11:0]功能
1.将rs1与12位立即数(进行符号位扩展)相加,并将结果存到rd寄存器中去,如果结果溢出,舍弃溢出位,不做处理,保留低32位结果
2.addi rd,rs1,0指将rs1寄存器中的值存入rd中去
为什么没有立即数减法 *** 作?
因为addi运算是带符号位进行运算的,可以用addi rd,rs1,-10实现rd=rs1-10功能
add rd,rs1,rs2 sub rd,rs1,rs2功能
1.将rs1与rs2相加,并将结果存到rd寄存器中去,如果结果溢出,舍弃溢出位,不做处理,保留低32位结果,sub指令类似
x0特殊寄存器通过硬件方式,x0寄存器固定为0,为只读寄存器
add x3,x4,x0功能
1.将x4赋值给x3
2. 访问存储指令rv32有32个寄存器,从x0到x31
zero:x0
首先明确一下,在RV32中1字(word)=4(bytes)=32(bit),内存是以字节为单位,一个字的内存由4字节组成。默认小端模式其中寄存器访问速度大概是DRAM的100~500倍。小端模式下,一个字的地址与它最低位的字节地址相同。
c code: int A[100]; g=h+A[3] s code: lw x10,12(x15) add x11,x12,x10
功能x15存放A数组的基地址,12表示偏移量(偏移地址),12(x15)即表示A[3]
注意:偏移地址在RV32中在字为 *** 作单元的指令中需为4的倍数,如:lw、sw
1.lw读一个32位的数据,存入寄存器中。
lb、lbu、sw、sblb rd,offset[11:0](res) #读一个8位数据,并进行符号位扩展 用于有符号数 lbu rd,offset[11:0](res) #读一个8位数据,并进行高位补零 用于无符号数** sw rs2,offset[11:0](res) #写 sb rs2,offset[11:0](res) #写
为什么需要符号位或者高位扩展?
因为当从存储器读一个8位数据到寄存器时,寄存器为32位故需要扩展。
指令后加u代表对无符号数 *** 作
beq rs1,rs2,label #相等跳 bne rs1,rs2,label #不相等跳 bge rs1,rs2,label #大于等于跳 有符号数 bgeu rs1,rs2,label #大于等于跳 无符号数 blt rs1,rs2,label #小于 bltu rs1,rs2,label #
if-else例子:
j label #无条件跳转4.逻辑运算指令
and rd,rs1,rs2 将rs1和rs2进行与运算,结果存rd or rd,rs1,rs2 将rs1和rs2进行或运算 xor rd,rs1,rs2 将rs1和rs2进行异或或运算 sll rd,rs1,rs2 逻辑左移(低位补零) srl rd,rs1,rs2 逻辑右移(高位补零) sra rd,rs1,rs2 算术右移(高位补符号位)
小练习逻辑非实现:使用异或 *** 作,例如:xor rd,rs1,0xff,表示rs1寄存器低八位取非算术右移与逻辑右移运算区别?
逻辑运算不考虑符号位,右移左边直接添零,算术运算考虑符号位,左边添加符号位
在算术运算中右移n位并不一定代表除以2的n次方,如图
5. 函数调用答案:0x3400
函数调用常用到的寄存器1.每条指令都以32位(4字节)机器码形式存放在存储器中
2.函数数调用的六个过程
①. 函数调用时,执行函数前,先将调用中要用到的参数保存;
②.控制权移交给调用的功能函数;
③.申请存储空间,满足执行过程中内存开耗
④.执行函数的功能 *** 作
⑤.函数执行完后,保存结果数据,同时还原函数执行过程中使用到的寄存器值、释放分配给函数的本地存储空间(局部变量等)。
⑥.释放控制权
a0-a7(x10-x17):8个寄存器用于传递参数,a0-a1常用于传递返回值
x1(ra):用于放置原函数返回地址
x2(sp):堆栈指针
s0-s11和s2-s11:用于保存原函数的关键数据,不受破坏
注意: ra寄存器中的返回地址,为当前地址+4,zero代指x0寄存器 hard zero
6.函数调用及栈的使用解释:j label和jr r1的区别是j是跳转到一个具体的地址,而jr是跳转到一个寄存器地址,sum的函数调用肯定会发生在不同地点,故函数返回值都不相同一般使用ret指令代替jr ra指令使用jal ra,label跳转指令,可保存函数返回值到ra中去,值为pc+4
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)