struct 的成员在内存中按顺序排列,可能带有填充,并且结构的地址通常是其第一个成员的地址。
struct Bar {
int x;
int y;
};
struct Foo {
struct Bar b;
double d;
int i;
};
struct Foo f;
假设&f 是0x10。那么&f.b.x(Foo的第一个成员)也是0x10。 &f.b.y 是 0x14,因为 f.b.x 是四个字节(假设是 32 位机器)。 &f.d 是 0x18,&f.i 是 0x20。第一个未被f(即&f + 1)占用的地址是0x24。
所以你在汇编中需要做的就是确保你有(堆栈或堆)空间用于结构的成员,并用适当的数据填充空间,并将第一个成员的地址传递给函数.
对于一个实际涉及汇编的示例,您可以通过编写一个小测试程序并使用gcc -S -O0 -g 编译它来轻松地自己生成它,这将为您的C 代码生成汇编代码。例如:
int func(struct Foo * foo) {
return foo->b.x + foo->i;
}
int main() {
struct Foo foo;
foo.b.x = 42;
foo.b.y = 9;
foo.d = 3.14;
foo.i = 8;
func(&foo);
return 0;
}
在汇编输出中,您将看到(注意:这是 64 位 ASM):
movl $42, -32(%rbp)
movl $9, -28(%rbp)
movabsq $4614253070214989087, %rax
movq %rax, -24(%rbp)
movl $8, -16(%rbp)
如您所见,值 42、9(位模式为 3.14 的整数)和 8 被加载到地址 -32、-28、-24 和 -16(相对于基指针)。我手边只有一个 Solaris 盒子,所以我不能使用 asmlinkage(它指定函数参数必须在堆栈中而不是在寄存器中传递),所以在函数调用之前,我们看到了有效地址被加载到寄存器中的结构:
leaq -32(%rbp), %rax
movq %rax, %rdi
使用asmlinkage,您会看到这个有效地址被压入堆栈。