assembly 什么是程序集中的“%rdi”,它在何处取值?[duplicate]

olmpazwi  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(208)

此问题在此处已有答案

What are the names of the new X86_64 processors registers?(4个答案)
What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64(4个答案)
What's the best way to remember the x86-64 System V arg register order?(1个答案)
Where is the x86-64 System V ABI documented?(3个答案)
2天前关闭。
由于对this post about UB很感兴趣,我决定开始阅读Jonathan Bartlett's Programming from the Ground Up,以便使用C++ UB,看看程序集是什么样子的。
但是在尝试的过程中,我在一个非常简单的例子中发现了一些奇怪的东西。

int foo(int * p) {
    int y = 7;
    if (p)
        ++y;
    return y;
}

其装配

foo(int*):
        cmpq    $1, %rdi
        movl    $7, %eax
        sbbl    $-1, %eax
        ret

Compiler Explorer
现在我明白了movl $7, %eax将值7放入eax寄存器,然后ret将其返回给调用者。所以我也明白了sbbl $-1, %eax是负责从eax的内容中减去-1并将结果存储到eax本身的指令,而且这个指令只有在p不为空时才会发生,这就导致我假设sbbl正在使用前面几行计算出的隐藏布尔值,唯一的候选值,即使是名字,也是cmpq $1, %rdi
但是 that 在做什么呢?从前面提到的书中,我了解到函数的参数是通过堆栈从调用者传递到被调用者的:调用者将参数推入堆栈,被调用者提取这些值。但这里没有这样的事情。
那么%rdi是什么呢?函数的第一个参数的寄存器(在这个例子中也是唯一的)?为什么会这样呢?还有其他寄存器引用更多的参数吗?有多少?此外,关于这个主题,什么是好的信息来源?

yjghlzjz

yjghlzjz1#

%rdi是对寄存器rdi的引用。
在这种情况下,编译器似乎是在寄存器中而不是在堆栈上传递第一个参数。
参数传递基本上是一种约定:只要编译器在如何传递参数方面是一致的,编译器就可以在它认为合适的任何时候(编译器的新版本,或者甚至只是在编译器命令行上传递一些开关)从一种方式(例如,总是在堆栈上)传递参数切换到另一种方式(一些在寄存器中)。
取决于您查看的时间和位置,单个编译器支持多个调用约定是很常见的。例如,在相当长的一段时间内,Microsoft的32位编译器支持四个调用约定:cdeclfastcallstdcallthiscall(最后一个仅用于C++成员函数)。其中,cdeclstdcall完全基于堆栈,fastcallthiscall都使用寄存器来处理某些参数。

相关问题