【问题标题】:What is "%rdi" in assembly and where does it take its value? [duplicate]汇编中的 \"%rdi\" 是什么,它的值在哪里? [复制]
【发布时间】:2022-11-22 03:39:46
【问题描述】:

对 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。

但是什么是那正在做?从前面提到的书中,我了解到函数参数是通过堆栈从调用者传递给被调用者的:调用者将参数压入堆栈,而被调用者提取这些值。但是这里没有这样的东西。

那么%rdi 是什么?函数的第一个(在本例中仅)参数的寄存器?为什么会这样?是否有其他寄存器引用进一步的参数?多少?此外,有关此主题的良好信息来源是什么?

【问题讨论】:

  • RDI 持有 x86-64 System V 调用约定中的第一个整数/指针 arg。您正在阅读的书使用 32 位 x86 程序集,其中标准调用约定更旧且效率更低,仅使用堆栈参数。

标签: c++ assembly parameter-passing x86-64 cpu-registers


【解决方案1】:

%rdi 是对寄存器rdi 的引用。

在这种情况下,编译器似乎是在寄存器中而不是在堆栈中传递第一个参数。

参数传递基本上是一种约定:只要编译器在传递参数方面保持一致,编译器几乎可以在它认为合适的任何时候从一种方式(例如,总是在堆栈上)传递参数切换到另一种方式(一些在寄存器中) (新版本的编译器,甚至只是在编译器命令行上传递一些开关)。

【讨论】:

    猜你喜欢
    • 2016-03-28
    • 2021-12-17
    • 2017-02-27
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 2019-07-05
    • 2010-12-27
    相关资源
    最近更新 更多