C 一个简单程序的GDB反汇编
这里是一个简单的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”));
#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
周围的括号是什么意思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字节都被使用。堆栈用于将参数从一个函数传递到另一个函数。调用函数在堆栈上分配空间(创建堆栈帧),被调用方(被调用的函数)可以访问堆栈中的参数。