在汇编中,你如何处理C struct?

R__*_*R__ 9 assembly

例如,如何为此准备参数syscall sys_wait4:

 asmlinkage long sys_wait4(pid_t pid,unsigned int __user *stat_addr, int options, struct rusage __user *ru)
1120 {
Run Code Online (Sandbox Code Playgroud)

如何处理struct rusage装配?

一个hello world例子来处理struct汇编对我来说已经足够了:)

Aas*_*set 14

a的成员struct按顺序排列在内存中,可能带有填充,结构的地址通常是其第一个成员的地址.

struct Bar {
    int x;
    int y;
};

struct Foo {
    struct Bar b;
    double d;
    int i;
};

struct Foo f;
Run Code Online (Sandbox Code Playgroud)

让我们说&f是的0x10.然后,&f.b.x(第一个成员的第一个成员Foo)也是0x10.&f.b.y0x14,因为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;
}
Run Code Online (Sandbox Code Playgroud)

在汇编输出中,除其他外,您将看到(注意:这是64位ASM):

movl    $42, -32(%rbp)
movl    $9, -28(%rbp)
movabsq $4614253070214989087, %rax
movq    %rax, -24(%rbp)
movl    $8, -16(%rbp)
Run Code Online (Sandbox Code Playgroud)

如您所见,值42,9(位模式为3.14的整数)和8加载到地址-32,-28,-24和-16(相对于基指针).我只有一个方便的Solaris盒子,所以我无法使用asmlinkage(它指定函数参数必须在堆栈而不是寄存器中传递),所以在函数调用之前,我们看到struct的有效地址是加载到寄存器:

leaq    -32(%rbp), %rax
movq    %rax, %rdi
Run Code Online (Sandbox Code Playgroud)

有了asmlinkage,你会看到这个有效的地址被推入堆栈.

  • 我认为 C99 保证结构的地址是其第一个成员的地址。 (2认同)
  • @R__:您可以通过要求编译器输出程序集来自己生成一个。请参阅我更新的答案。 (2认同)