main:addisp,sp,-32# 将栈指针sp向下移动32个字节,预留栈空间swra,28(sp) # 将返回地址ra存储到栈的偏移28字节处sws0,24(sp) # 将保存寄存器s0存储到栈的偏移24字节处addis0,sp,32# 设置帧指针s0,指向当前栈顶lia5,2# 将立即数2加载到寄存器a5swa5,-20(s0) # 将a5的值存储到栈的偏移-20字节处l...
1 RISC-V ABI接口 ABI(Application Binary Interface)为应用程序二进制接口,它定义了应用程序之间或应用程序和操作系统之间进行二进制级交互时必须遵循的规则和约定。ABI包括了关于函数调用约定(参数传递,函数返回值等)、数据类型、对齐方式、字节序、 函数栈布局、系统调用等方面的规范。 具体来说,ABI定义了以下内容:...
在RISC-V汇编语言中,函数调用的过程可以分为以下几个步骤: 1. 保存寄存器状态:在调用函数之前,需要将当前函数中需要使用的寄存器的值保存到栈中,以防止被调用函数修改这些值。通常使用指令"addi sp, sp, -n"将栈指针sp向下移动n个字节,然后使用指令"sw reg, 0(sp)"将需要保存的寄存器的值存储到栈中。 2....
调用者保存(Caller-saved):临时寄存器(t0-t6)和参数寄存器(a0-a7)。调用函数前,调用者需要保存这些寄存器的值。 被调用者保存(Callee-saved):保存寄存器(s0-s11)和返回地址寄存器(ra)。被调用函数需要保存和恢复这些寄存器的值。 # 调用者函数 caller_function: # 保存调用者保存寄存器 addi sp, sp, -16 sd ...
对于caller saved和callee saved寄存器有点不清楚,参考RISC-V手册总结一下: 函数调用过程通常分为 6 个阶段[Patterson and Hennessy 2017]。 将参数存储到被调用的函数可以访问到的位置; 跳转到函数起始位置; 获取函数需要的局部存储资源,按需保存寄存器(callee saved registers) ; ...
当我们调用函数时,你可以看到这里有a0 - a7寄存器。通常我们在谈到寄存器的时候,我们会用它们的ABI名字。不仅是因为这样描述更清晰和标准,同时也因为在写汇编代码的时候使用的也是ABI名字。 第一列中的寄存器名字并不是超级重要,它唯一重要的场景是在RISC-V的Compressed Instruction中。
在本文,通过分析glibc库中的pthread_create函数来说明在riscv架构的处理器中,怎样实现syscall调用的。 pthread_create 函数声明在 pthread.h 头文件中,其调用的是一个__pthread_create_2_1 的函数,并且其位置在 ./nptl/pthread_create.c 文件中. 下面的 versioned_symbol 格外吸引我的注意,因为它使 __pthread_...
由于涉及调用到了add函数,add函数有两个参数需要传参,需要把值101和202作为两个入参传入,在riscv中,入参寄存器默认为a0, a1……等以此类推。所以此处将栈中的值取出,分别赋值给a0, a1。 在add函数中,首先是在原来的地址基础上,继续开辟一块栈空间为32字节。第一步是保存返回地址,当add函数运行结束的时候跳转...
在RISC-V架构中,函数的执行顺序遵循一定的流程。下面我们来看一下RISC-V函数执行的顺序。 1. 函数调用。 当一个函数被调用时,程序会将函数的参数传递到指定的寄存器中,然后通过JAL(Jump and Link)指令跳转到函数的入口地址。 2. 函数入口。 在函数的入口,程序会保存调用者保存寄存器的值,并为该函数创建一个新...
不过幸运的是 RISC-V 寄存器的 “ABI” 命名规则,有助于程序员理解它们的含义。比如: 整数参数在寄存器 A0-A7 中,浮点参数在寄存器 FA0-FA7 中 通过对堆栈指针的 sub 操作去分配函数堆栈。在调用完成后使用 add 操作进行销毁 堆栈大小必须以 8 的整数倍形式分配...