在汇编代码中按引用/按指针

By-reference / by-pointer in assembly code

本文关键字:引用 指针 汇编 代码      更新时间:2023-10-16

我想看看c++中按引用调用和按指针调用有什么不同。
然而,g++编译器(使用- 0 -S)产生相同的代码。
我试图"欺骗"编译器,用各种人为的构造来产生某种差异,但它似乎比我更聪明。
是否有一种方法可以关闭gcc中的所有智能,以便我可以理解汇编中引用的实现?

[编辑]

/* Testing assembly representation of ref/pointer/by-value parameters */
int byRef(int &value, int value2) {
    value = value2;
    return value;
}
int byPtr(int * value, int value2) {
    *value = value2;
    return *value;
}

int main(int argc, char * argv[]) {
    int value = 5;
    byRef(value, value);
    byPtr(&value, value);
}

call    ___main
movl    $5, -4(%ebp)
movl    -4(%ebp), %eax
movl    %eax, 4(%esp)
leal    -4(%ebp), %eax
movl    %eax, (%esp)
call    __Z5byRefRii
movl    -4(%ebp), %eax
movl    %eax, 4(%esp)
leal    -4(%ebp), %eax
movl    %eax, (%esp)
call    __Z5byPtrPii
movl    $0, %eax

这里也没有区别。是否有一种简单的方法来触发语义重用?

真的没有什么需要理解的了。

引用指针,引用不是指针。

更准确地说,引用当然不是指针,而是别名。这意味着从语义上讲,它们是相同的变量,只是名称不同。这意味着编译器通常可以使用巧妙的重命名技巧来完全优化引用的传递。

有时,它仍然必须以某种方式传递引用,然后通常通过指针来传递引用(这不是必需的,但恰好是一种适合的技术)。与指针的唯一可观察到的区别是,在底层,引用不能为空,编译器知道这一点(尽管,如果你足够恶意,你可以创建一个空引用)。

不,没有别的了。引用是存在于其他地方的某个对象的另一个名称,别名。

您现在已经了解到,在这种情况下,引用是使用它所引用的对象的地址(作为实现细节)实现的。语言并没有说明这应该如何工作,只是说明了效果是什么。

使用对象的地址似乎是一个简单的解决方案,当然,实际上每个实现都使用

是否有一种方法可以关闭gcc中的所有聪明,以便我可以理解汇编中引用的实现?

显然不是。换句话说:你已经看到了:引用传递通常是通过指针实现的。

应该考虑两层语义——c++和ASM。ASM语义不包含引用,因此引用和指针被转换为指针(在其他答案中已经提到了)。

然而,翻译规则可能有所不同。试着试试这样写:

int i = 7;
int * pi = i;
int & ri = i;
int &* rpi = pi;
int *& pri = &ri;

来打破它的等价性。同时也要尝试查看[ARM]中引用和指针的详细描述。我不确定我的回答是否对你有帮助,但希望如此。如果你发现反例,请反馈。我也很感兴趣。

这都是关于语义上下文的!

引用是生成的二进制代码上下文中的指针。

引用仅在从c++到ASM的转换阶段是引用。

c++标准没有告诉编译器编写者如何实现他们的编译器。但实际上,没有其他方便的方法在编译器中实现引用。