C 一个简单程序的GDB反汇编

C 一个简单程序的GDB反汇编,c,gcc,assembly,x86,gdb,C,Gcc,Assembly,X86,Gdb,这里是一个简单的C语言程序,我使用gdb对其进行反汇编,以了解发生了什么 #include <stdio.h> #include <string.h> int main(){ printf("%d", sizeof(foo("HELLOWORLD"))); } int foo(char* c) { printf("%s\n",c); } #包括 #包括 int main(){ printf(“%d”,sizeof(foo(“HELLOWORLD”));

这里是一个简单的C语言程序,我使用gdb对其进行反汇编,以了解发生了什么

#include <stdio.h>
#include <string.h>
int main(){
    printf("%d", sizeof(foo("HELLOWORLD")));
}

int foo(char* c)
{
   printf("%s\n",c);
}
#包括
#包括
int main(){
printf(“%d”,sizeof(foo(“HELLOWORLD”));
}
int foo(字符*c)
{
printf(“%s\n”,c);
}
下面是拆解主泵的相应装配代码

0x08048414 <+0>:    push   %ebp
   0x08048415 <+1>: mov    %esp,%ebp
   0x08048417 <+3>: and    $0xfffffff0,%esp
   0x0804841a <+6>: sub    $0x10,%esp
   0x0804841d <+9>: mov    $0x8048520,%eax
   0x08048422 <+14>:    movl   $0x4,0x4(%esp)
   0x0804842a <+22>:    mov    %eax,(%esp)
   0x0804842d <+25>:    call   0x8048320 <printf@plt>
   0x08048432 <+30>:    leave  
   0x08048433 <+31>:    ret   
0x08048414:推送%ebp
0x08048415:mov%esp,%ebp
0x08048417:和$0xfffffff0,%esp
0x0804841a:子$0x10,%esp
0x0804841d:mov$0x8048520,%eax
0x08048422:movl$0x4,0x4(%esp)
0x0804842a:mov%eax,(%esp)
0x0804842d:呼叫0x8048320
0x08048432:离开
0x08048433:ret
下面是分解foo

0x08048434 <+0>:    push   %ebp
   0x08048435 <+1>: mov    %esp,%ebp
   0x08048437 <+3>: sub    $0x18,%esp
   0x0804843a <+6>: mov    0x8(%ebp),%eax
   0x0804843d <+9>: mov    %eax,(%esp)
   0x08048440 <+12>:    call   0x8048330 <puts@plt>
   0x08048445 <+17>:    leave  
   0x08048446 <+18>:    ret  
0x08048434:推送%ebp
0x08048435:mov%esp,%ebp
0x08048437:子$0x18,%esp
0x0804843a:mov 0x8(%ebp),%eax
0x0804843d:mov%eax,(%esp)
0x08048440:呼叫0x8048330
0x08048445:离开
0x08048446:ret
我对这些说明感到困惑:

  • 0x08048417和$0xFFFFF0,%esp
    为什么堆栈指针在未修改之前需要对齐

  • 0x0804841a:sub$0x10,%esp
    这条指令具体对程序做了什么

  • 0x0804841d:mov$0x8048520,%eax
    此指令对程序有什么特殊作用

  • mov%eax,(%esp)
    %esp
    周围的括号是什么意思

  • 如果有人解释一下,会很有帮助的

  • 属于(函数)序言,它通过对SP进行位屏蔽,将SP与16字节边界对齐

  • 创建堆栈帧的内存,因为需要将指针传递给函数。地址将从堆栈传递到函数。然而,该表达式似乎是在编译时执行的,因此不需要实际调用

  • 0x8048520
    可能是字符串“%d”的地址。它被放入eax,从那里开始,它被使用stackpointer放在堆栈上


  • 周围有很多材料,例如。

    1)对齐堆栈,2)在堆栈上保留空间,3)hello world的地址,4)查看调用约定。为什么正好是16字节的空格?Wrt对齐:您不知道指针以前在哪里。Wrt括号,它们类似于C指针的
    *
    。@ZhangYuan:
    foo
    根本不被调用,因为它在
    sizeof
    运算符中使用,后者完全在编译时计算。@ZhangYuan:它是相对于过程链接表的地址。当程序启动时,OS加载器将“修复”此地址,以指向共享库中的
    printf
    的实际代码。但由于没有调用函数foo(main中没有调用指令)为什么要将Hello world添加到堆栈中..是否每次调用新函数时都需要对齐SP?@bash.d:它不是“HELLOWORLD”的地址,很可能是printf格式字符串的地址
    foo
    根本不被调用,因为整个
    sizeof
    操作符在编译时计算为
    4
    。printf的地址为0x0804832b@vindhya:使用堆栈指针将
    操作“向下舍入”到最近的16字节边界。将数据放在这样的边界可以使计算机更有效地获取和处理数据。实际上并不是所有的16字节都被使用。堆栈用于将参数从一个函数传递到另一个函数。调用函数在堆栈上分配空间(创建堆栈帧),被调用方(被调用的函数)可以访问堆栈中的参数。