assembly - 为什么 RISC-V 中 "long long"参数需要 "aligned even-odd register pair"

标签 assembly calling-convention riscv

RISC-V calling convention documentation说:

When primitive arguments twice the size of a pointer-word are passed on the stack, they are naturally aligned. When they are passed in the integer registers, they reside in an aligned even-odd register pair, with the even register holding the least-significant bits. In RV32, for example, the function void foo(int, long long) is passed its first argument in a0 and its second in a2 and a3. Nothing is passed in a1.

为什么不直接使用a1a2而不是a2a3?所以我们可以通过寄存器传递更多的参数。

最佳答案

通常,这样做是为了让简单的代码可以将所有寄存器刷新到内存并获得您所期望的内容,就好像内存首先被用来传递对齐良好的参数一样 - 这通常很重要带有可变参数函数。

但是,我们应该注意,对于非可变参数函数,clang 和 gcc 都没有直接遵循这一点。它们都使用 a0 表示 inta1a2 表示 long long (其中a1long long的低位,a2是高位)。

long long square(int num, long long foo) {
    return foo + 100;
}

结果

square:
    addi    a0, a1, 100
    sltu    a1, a0, a1
    add     a1, a1, a2
    ret

铿锵:https://godbolt.org/z/9Pez4r

海湾合作委员会:https://godbolt.org/z/b4dMsr


只有当我们使用可变参数时,编译器才会跳过a1:

long long square(int num, ...);

int test () {
    square ( 100, (long long) 200 );
}

结果

test:
    addi    a0, zero, 100
    addi    a2, zero, 200
    mv      a3, zero
    tail    square

https://godbolt.org/z/4xWc1E

关于assembly - 为什么 RISC-V 中 "long long"参数需要 "aligned even-odd register pair",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65575302/

相关文章:

c++ - 优化处理标签(空结构)函数参数

c - "pointer to register variable"作为函数参数有什么作用?

riscv - 如何在 RISC-V 中生成 hex 文件

rust - 为什么我不能在 QEMU 中启动自定义内核?

assembly - 在 RISC-V 汇编中写入几个 MMIO 寄存器位的更好方法?

java - CPMXCG(比较和交换)在多处理器机器上到底如何工作?

c - 优化版本代码中的 SIGSEGV

linux - 如何在 x86_64 程序集中打印字符串

assembly - 在 64 位平台上使用 ld 生成 32 位可执行文件

linux - ARM 在 WinCE 和 Linux 上的调用约定?