废话:
大三老菜狗来更新啦,哎,感叹一下生活不易,天天犯困。记得去看书哦。最近看到那个jetson好心动啊,树莓派性能和jetson相比就是垃圾,但理性告诉我jetson的性能在我这完全是过剩的。
注释:
RISC-V汇编学习笔记系列是RISC-V学习笔记系列下的一个分支,在这里着重讲解的是RISC-V的汇编指令是如何实现的。对读懂RISC-V有一定的帮助,但因为不是主线剧情所以会更加随意一点。
程序段与函数调用的实现:
1.每条指令都是以32位的机器码形式存放在寄存器中
2.一般情况下指令是顺序执行,更新得PC值是原值+4,但遇到转移分支指令时,需要根据转移情况更新为跳转位置的地址值。
3.在RISC-V中,所有指令都是4字节
4.函数调用可能发生在程序段的多个位置,每次函数调用时返回地址都会随发生调用时地址的不同而不同
5.需要在函数调用前记录下返回地址保存在ra寄存器中,返回时再利用jr指令返回到ra寄存器中保存的地址值,保证多次调用的灵活性。
函数调用的基本步骤:
1.放置传递参数:发生函数调用时,在执行函数功能前,先将这次调用中需要用到的参数保存,方便取用。
2.移交控制权到函数:将控制权移交给这次调用的功能函数。
3.申请函数的存储空间:根据情况为函数申请一定的本地储存空间,以满足函数执行过程中需要的存储需求。
4.执行函数功能:执行该函数的功能操作。
5.存放结果值、释放存储空间:在函数执行完成后,将的到的结果数据存放好,以便主进程获取,同时还原函数执行过程中使用到的寄存器值、释放分配给函数的本地存储空间。
6.返还控制权到调用者:将控制权返还给原进程。
RISC-V寄存器类型:
1.zero(零寄存器):编号为x0的寄存器,用于做源寄存器(rs)或目标寄存器(rd)
2.ra(链接寄存器):编号为x1的寄存器,用于保存返回时的返回地址。
3.sp(栈指针寄存器):编号为x2的寄存器,用于指向栈的地址。
4.gp(全局寄存器):编号为x3的寄存器,用于链接器松弛优化。
5.tp(线程寄存器):编号为x4的寄存器,用于在OS中保存指向进程控制块(task_struct)数据结构的指针。
6.t0 ~ t6(临时寄存器):编号为x5 - x7和x28 - x31的寄存器
7.s0 - s11:编号为x8 - x9和x18 - x27的寄存器,用于作为保存寄存器,保存原进程中的关键数据,避免在函数调用过程中被破坏。其中x8(s0/fp)又被称为帧指针寄存器。
8.a0 - a7:编号为x10 - x17的寄存器,用于向调用的函数传递参数,a0和a1寄存器常用于传递返还值。
Jump and link(jal)指令(有点抽象):
1008 addi ra, zero, 1016 # ra = 1016
1012 j sum # goto sum ——> 1008 jal sum # ra = 1016,goto sum
1.jal指令(跳转并链接):通过jal指令,可以形成指向调用点的地址或链接,从而使函数能返回正确的地址。跳转会使PC跳转指向被调用函数的地址,并将链接得到的下一指令的地址作为返回地址,保存到ra寄存器当中。
jr指令:
能跳转到寄存器值所对应的地址空间,使用这条指令跳转到ra寄存器保存的地址值以实现函数的返回。再汇编中,有用ret指令来代指jr ra的操作。