return 值 Vs 参考(在汇编中)
return value Vs reference (in assembly)
在查看了有关该主题的几个问题(和答案)后,我在 Compiler Explorer.
中尝试了以下简单代码
#include <iostream>
class TwoInts
{
public:
TwoInts( ) = default;
const int& getAByRef( ) const;
int getAByVal( ) const;
private:
int a;
int b;
};
const int& TwoInts::getAByRef( ) const
{
return a;
}
int TwoInts::getAByVal( ) const
{
return a;
}
int main( )
{
TwoInts ti;
const int& num1 { ti.getAByRef( ) };
const int num2 { ti.getAByVal( ) };
//std::cout << num1 << ' ' << num2 << '\n';
}
现在我看到为两个成员函数 getAByRef
和 getAByVal
生成了不同的代码:
TwoInts::getAByRef() const:
mov rax, rdi
ret
TwoInts::getAByVal() const:
mov eax, DWORD PTR [rdi]
ret
谁能解释一下这两条不同的汇编指令在做什么?
每个成员函数都获取 this
指针作为隐式第一个函数参数,正如 GCC 使用的 Itanium ABI(不要与 Itanium 体系结构混淆)所规定的那样。 this
在 rdi
寄存器中传递,一个值在 rax
(eax
) 寄存器中被 returned(如果它是微不足道的,这里是)根据 x86-64 System V ABI(参见下面 Peter Cordes 的评论)。
在第一种情况下,当您通过引用 return a
时,您实际上是在 return 获取 a
的地址。 a
是第一个成员,所以它的地址与对象的地址相同,即this
。因此,您只需将 rax
设置为 rdi
。
在第二种情况下,当您按值 return a
时,您需要进行实际的取消引用。这就是 DWORD PTR [rdi]
正在做的事情。 DWORD PTR
表示你想要获取 4 个字节 (sizeof(int)
).
如果你把一些数据成员放在 a
之前,你会看到一个额外的偏移量添加到 rdi
。
在查看了有关该主题的几个问题(和答案)后,我在 Compiler Explorer.
中尝试了以下简单代码#include <iostream>
class TwoInts
{
public:
TwoInts( ) = default;
const int& getAByRef( ) const;
int getAByVal( ) const;
private:
int a;
int b;
};
const int& TwoInts::getAByRef( ) const
{
return a;
}
int TwoInts::getAByVal( ) const
{
return a;
}
int main( )
{
TwoInts ti;
const int& num1 { ti.getAByRef( ) };
const int num2 { ti.getAByVal( ) };
//std::cout << num1 << ' ' << num2 << '\n';
}
现在我看到为两个成员函数 getAByRef
和 getAByVal
生成了不同的代码:
TwoInts::getAByRef() const:
mov rax, rdi
ret
TwoInts::getAByVal() const:
mov eax, DWORD PTR [rdi]
ret
谁能解释一下这两条不同的汇编指令在做什么?
每个成员函数都获取 this
指针作为隐式第一个函数参数,正如 GCC 使用的 Itanium ABI(不要与 Itanium 体系结构混淆)所规定的那样。 this
在 rdi
寄存器中传递,一个值在 rax
(eax
) 寄存器中被 returned(如果它是微不足道的,这里是)根据 x86-64 System V ABI(参见下面 Peter Cordes 的评论)。
在第一种情况下,当您通过引用 return a
时,您实际上是在 return 获取 a
的地址。 a
是第一个成员,所以它的地址与对象的地址相同,即this
。因此,您只需将 rax
设置为 rdi
。
在第二种情况下,当您按值 return a
时,您需要进行实际的取消引用。这就是 DWORD PTR [rdi]
正在做的事情。 DWORD PTR
表示你想要获取 4 个字节 (sizeof(int)
).
如果你把一些数据成员放在 a
之前,你会看到一个额外的偏移量添加到 rdi
。