如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.
为什么不直接使用a1
和a2
而不是a2
和a3
?所以我们可以通过寄存器传递更多的参数。
最佳答案
通常,这样做是为了让简单的代码可以将所有寄存器刷新到内存并获得您所期望的内容,就好像内存首先被用来传递对齐良好的参数一样 - 这通常很重要带有可变参数函数。
但是,我们应该注意,对于非可变参数函数,clang 和 gcc 都没有直接遵循这一点。它们都使用 a0
表示 int
和 a1
、a2
表示 long long
(其中a1
是long 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
关于assembly - 为什么 RISC-V 中 "long long"参数需要 "aligned even-odd register pair",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65575302/