可以看到: main函数使用jal指令,跳转到函数a,并且设置了ra寄存器(这是jal指令的操作)。 接着在函数a()内,首先把ra寄存器的值存储到栈上,然后开始执行其他操作。 在函数a()将要返回的时候,从栈上取出ra的值,并设置到ra寄存器内,于是ret指令就能返回到main函数了。
再看x1 寄存器,它常被当作返回地址寄存器(ra),当程序执行函数调用时,它就像个 “小书签”,默默记下当前位置,等函数执行完,就能依据它存的地址,准确回到原来的代码行继续执行,保证程序流程顺畅。x2 寄存器作为栈指针寄存器(sp),掌控着函数调用、局部变量存储相关的栈操作,函数调用时压栈保存现场、函数返回时弹栈恢...
对于这些通用寄存器,除了x0外(x0 寄存器的值读恒为0,写无效),其它寄存器都本质上是等价的。但在实际使用过程中,我们约定了这些寄存器的用法,即ABI规范,见下表,我们将x0-x31以及f0-f31 按照常用功能分别取了别名,附带有简单的描述,在汇编中使用原名和别名是等价的,比如:在汇编中我们使用x1或使用ra,编译器都是...
1 整数寄存器约定 RISCV中一共有32个整数寄存器。 1.1 特殊功能寄存器 x0 (zero):零寄存器,硬连线为0值,不可修改。用于提供常数0或清空操作。 x1 (ra):返回地址寄存器,存储函数调用的返回地址。 x2 (sp):堆栈指针,指向当前堆栈顶部。 x3 (gp)...
返回地址寄存器:ra(x1) 注意:不是返回值,call函数的时候的下一条指令 栈指针寄存器:sp(x2) 全局指针寄存器:gp(x3) 线程指针寄存器:tp(x4) 参数传递 前8个参数:通过参数寄存器 a0-a7 传递。 超过8个参数:通过栈传递,超出的参数会依次压入栈中。
下面是寄存器及其别名的对应关系:x0 / Zero x1 / ra (return address)x2 / sp (stack pointer)x3...
andi 指令是拿** a0 寄存器和立即数 0xff 进行与操作。由于立即数是 0xff,所以总是返回 a0 的低 8 位数据;and 指令则是拿 a0 和 a1 寄存器进行与操作,再把结果写入到 a0 寄存器**。 用VSCode 打开工程按下“F5”调试一下,如下所示: 上图中是执行完 andi a0,a0,0xff 指令之后,执行 jr ra 指令之前...
RV32I 可以比较两个寄存器并根据比较结果上进行分支跳转。比较可以是:相等(beq),不相等 (bne),大于等于(bge),或小于(blt)。 对于jal,有两种方式。rd = ra 或者 x0,当=ra则为有返回地址实现过程调用,=x0则为直接跳转。jal 将其 20 位分支地址乘以 2,进行符号扩展后再添加到 PC 上,便得到了跳转地址。
RISC-V CSR寄存器 CSR是控制状态寄存器,RISC-V中CSR寄存器,需要使用csrr、csrw、csrrw等特定指令进行访问。 M模式和S模式都有自己的CSR寄存器,但是大体上相同。下面列举一些常用的CSR。 M模式CSR寄存器 mstatus 状态寄存器,保存了全局中断使能状态和其他状态,例如切换模式前,保存当前模式。