在汇编中,你如何处理C结构体?

发布于 2024-11-17 20:47:42 字数 386 浏览 2 评论 0原文

比如这个syscall sys_wait4

 asmlinkage long sys_wait4(pid_t pid,unsigned int __user *stat_addr, int options, struct rusage __user *ru)
1120 {

汇编中如何处理struct rusage

在汇编中处理 struct 的 hello world 示例对我来说就足够了:)

For example, how to prepare parameters for this syscall sys_wait4:

 asmlinkage long sys_wait4(pid_t pid,unsigned int __user *stat_addr, int options, struct rusage __user *ru)
1120 {

How to deal with struct rusage in assembly?

A hello world example to deal with struct in assembly is enough for me:)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦归所梦 2024-11-24 20:47:42

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

struct Bar {
    int x;
    int y;
};

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

struct Foo f;

假设 &f0x10。那么,&fbxFoo的第一个成员的第一个成员)也是0x10&fby0x14,因为 fbx 是四个字节(假设是 32 位机器)。 &fd0x18&fi0x20。没有被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,您会看到该有效地址被推入堆栈。

The members of a struct are laid out sequentially in memory, possibly with padding, and the address of the struct is typically the address of its first member.

struct Bar {
    int x;
    int y;
};

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

struct Foo f;

Let's say that &f is 0x10. Then, &f.b.x (the first member of the first member of Foo) is also 0x10. &f.b.y is 0x14, since f.b.x is four bytes (assuming a 32-bit machine). &f.d is 0x18, and &f.i is 0x20. The first address that is not occupied by f (in other words, &f + 1) is 0x24.

So all you need to do in assembly is to make sure that you have (stack or heap) space for the members of the struct, and fill the space with appropriate data, and pass the address of the first member to the function.

As for an example that actually involves assembly, you could easily produce that yourself by writing a small test program and compile it with gcc -S -O0 -g, which will produce assembly code for your C code. For example:

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;
}

In the assembly output, you will, among other things, see (note: this is 64-bit ASM):

movl    $42, -32(%rbp)
movl    $9, -28(%rbp)
movabsq $4614253070214989087, %rax
movq    %rax, -24(%rbp)
movl    $8, -16(%rbp)

As you can see, the values 42, 9, (integer whose bit pattern is that of 3.14), and 8 being loaded into the addresses -32, -28, -24, and -16 (relative to the base pointer). I only have a Solaris box handy, so I couldn't use asmlinkage (which specifies that the function arguments must be passed on the stack rather than in the registers), so immediately before the function call, we see the effective address of the struct being loaded into a register:

leaq    -32(%rbp), %rax
movq    %rax, %rdi

With asmlinkage, you'd instead see this effective address being pushed onto the stack.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文