获取参数的地址在寄存器中传递

时间:2014-02-27 01:29:00

标签: c++ cpu-registers calling-convention

在带有pass-by-value的C ++中,调用者构造被调用者使用的副本。在x64 ABI中,一些参数在寄存器中传递。寄存器没有地址。

假设我有以下课程:

class Self_Pointer
{
    Self_Pointer* self;
    Self_Pointer(const Self_Pointer& obj) : self(this) {}
}

作为参数传递时,它会指向自身。现在我有了这个功能:

f(Self_Pointer x) {}

f()按值获取Self_Pointer,由调用约定传入寄存器。调用者f()必须在寄存器中创建副本。因此,调用者将在位于寄存器中的Self_Pointer上运行构造函数。但是,寄存器没有地址,因此无法运行构造函数。这种困境是如何解决的?

[编辑:按照Steve Jessop的回答,将班级的ctor修改为副本ctor。]

3 个答案:

答案 0 :(得分:2)

使用寄存器(或堆栈,用于参数传递)是特定编译器的实现细节。为了获得传递给函数的地址,编译器将寄存器的值复制到内存中的临时位置(通常在堆栈中),将其地址传递到需要的位置,然后从中加载数据。如果需要,临时位置回到同一个寄存器。

答案 1 :(得分:2)

首先,Self_Pointer的副本并不指向自己。它指向原始文件,因为编译器生成的复制构造函数将self的值从原始副本复制到副本。

因此,当您将副本传递给f时,实际上x并不指向自己。

如果通过为Self_Pointer编写合适的复制构造函数来解决此问题,则需要实现以确保x具有地址。如果这意味着不将它传递给寄存器,那么它就不会在寄存器中传递。通常ABI不会在寄存器中传递结构,除非它们是聚合类型,因为它有一个用户定义的构造函数,所以你的例子不是。

再举一个例子,考虑一下:

void foo(int i) {
   std::cout << &i << '\n';
}

同样,需要实施以安排i具有地址。如果它在寄存器中传递(并且如果x64寄存器在该特定硬件上没有地址),则函数foo必须将i溢出到堆栈。然后它将有一个像任何其他堆栈变量一样的地址。

答案 2 :(得分:0)

不,你不能。你得到的地址总是RAM的虚拟地址。您无法直接在C ++中访问寄存器的地址。