我想了解C调用约定。为此,我编写了以下代码:

#include <stdio.h>
#include <stdlib.h>

struct tstStruct
{
    void *sp;
    int k;
};

void my_func(struct tstStruct*);

typedef struct tstStruct strc;

int main()
{
    char a;
    a = 'b';
    strc* t1 = (strc*) malloc(sizeof(strc));
    t1 -> sp = &a;
    t1 -> k = 40;
    my_func(t1);
    return 0;
}

void my_func(strc* s1)
{
        void* n = s1 -> sp + 121;
        int d = s1 -> k + 323;
}

然后,我将GCC与以下命令结合使用:
gcc -S test3.c

并提出了它的组装。我不会显示完整的代码,而是粘贴函数my_func的代码。就是这个:
my_func:
.LFB1:
.cfi_startproc
pushq   %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq    %rsp, %rbp
.cfi_def_cfa_register 6
movq    %rdi, -24(%rbp)
movq    -24(%rbp), %rax
movq    (%rax), %rax
addq    $121, %rax
movq    %rax, -16(%rbp)
movq    -24(%rbp), %rax
movl    8(%rax), %eax
addl    $323, %eax
movl    %eax, -4(%rbp)
popq    %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc

据我了解,这是发生了什么:
首先,将调用者的基本指针压入堆栈,并使其堆栈指针成为新的基本指针,以为新功能设置堆栈。但是剩下的我不明白。据我所知,参数(或指向该参数的指针)存储在堆栈中。如果是这样,第二条指令的目的是什么,
movq        -24(%rbp), %rax

此处,%rax寄存器的内容被移到距离寄存器%rbp中的地址24个字节的地址。但是%rax是什么????最初什么都没有存储在那里???我觉得我很困惑。请帮助了解此功能的工作原理。
提前致谢!

最佳答案

您将AT&T语法与Intel语法混淆了。

movq -24(%rbp),%rax

用英特尔的语法是

mov rax,[rbp-24]

因此,它将rbp寻址的数据移动到rax,反之亦然。在AT&T语法中,操作数的顺序是src,dest,而在Intel语法中,操作数的顺序是dest,src。

然后,为了摆脱GAS指令以使反汇编更容易阅读,我将gcc的代码简单地与gcc test3.c组装在一起,并将其与ndisasm -b 64 a.out一起反汇编。请注意,以下由NDISASM生成的my_func函数的反汇编是使用Intel语法的:

000005EF 55推Rbp
000005F0 4889E5 mov rbp,rsp;创建堆栈框架。
000005F3 48897DE8 mov [rbp-0x18],rdi; s1转换为局部变量。
000005F7 488B45E8 mov rax,[rbp-0x18]; rax = s1(它是一个指针)
000005FB 488B00 mov rax,[rax];取消引用rax,将其存储到rax中。
000005FE 4883C079添加rax,字节+ 0x79; rax = rax + 121
00000602 488945F8 mov [rbp-0x8],rax;无效* n = s1-> sp + 121
00000606 488B45E8 mov rax,[rbp-0x18]; rax =指向s1的指针
0000060A 8B4008 mov eax,[rax + 0x8];取消引用rax + 8,存储到eax中。
0000060D 0543010000添加eax,0x143; eax = eax + 323
00000612 8945F4 mov [rbp-0xc],eax;整数d = s1-> k + 323
00000615 5D流行RBP
00000616 C3退出

有关Linux x86-64调用约定(系统V ABI)的信息,请参阅What are the calling conventions for UNIX & Linux system calls on x86-64的答案。

关于c - 了解C反汇编的调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16088946/

10-12 16:15