反汇编一个简单的C
来源:互联网 发布:中国十大禁菜 知乎 编辑:程序博客网 时间:2024/06/08 14:24
朱婷婷 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
计算机是怎么工作的?
我们知道计算机基本都是采用的冯诺依曼体系结构,它主要的核心思想就是存储程序计算机,指令和数据不加区别混合存储在同一个存储器中。CPU通过寄存器EIP指向内存从而获取内存中的数据。EIP总是指向内存的某一块区域(代码段),不断的指向下一条指令,每条指令的长度可能是不同的。我们可以用一个简单的图来描述下:
一、实验内容:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
main.c
int g(int x){ return x+4;}int f(int y){ return g(y);}int main(void){ return f(2)+4;}保存后执行以下命令:
gcc -S -o main.s main.c -m32其中gcc后面参数含义可以自行man以下,-S表示预处理后可直接对main.c文件编译生产汇编代码,如下所示:
shiyanlou:~/ $ cat main.s [21:59:59].file"main.c".text.globlg.typeg, @functiong:.LFB0:.cfi_startprocpushl%ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl%esp, %ebp.cfi_def_cfa_register 5movl8(%ebp), %eaxaddl$4, %eaxpopl%ebp.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc.LFE0:.sizeg, .-g.globlf.typef, @functionf:.LFB1:.cfi_startprocpushl%ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl%esp, %ebp.cfi_def_cfa_register 5subl$4, %espmovl8(%ebp), %eaxmovl%eax, (%esp)callgleave.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc.LFE1:.sizef, .-f.globlmain.typemain, @functionmain:.LFB2:.cfi_startprocpushl%ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl%esp, %ebp.cfi_def_cfa_register 5subl$4, %espmovl$2, (%esp)callfaddl$4, %eaxleave.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc.LFE2:.sizemain, .-main.ident"GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2".section.note.GNU-stack,"",@progbits二、实验结果分析:
以上汇编代码中,以点(.)开头的都是用于链接的辅助信息,这些信息是不会被执行的。因此以下分析下除去辅助信息之外的汇编指令:
g:pushl%ebpmovl%esp, %ebpmovl8(%ebp), %eaxaddl$4, %eaxpopl%ebpretf:pushl%ebpmovl%esp, %ebpsubl$4, %espmovl8(%ebp), %eaxmovl%eax, (%esp)callgleaveretmain:pushl%ebpmovl%esp, %ebpsubl$4, %espmovl$2, (%esp)callfaddl$4, %eaxleaveret
程序从main函数开始,假设一开始是一个空栈,如下图所示(在32位环境中,int型数据占4个zi)
pushl%ebp
movl%esp, %ebp
subl$4, %esp
movl$2, (%esp)
callfcall f 的操作其实就相当于pushl %eip; movl * f, %eip; 从这步开始进入到f函数中的操作
pushl%ebp
movl%esp, %ebp
subl$4, %esp
movl8(%ebp), %eax以上操作相当于 eax = *(int32_t *) (ebx+4),因此eax = 2
movl%eax, (%esp)
callg
pushl%ebp
movl%esp, %ebp
·
movl8(%ebp), %eax
addl$4, %eax
popl%ebp
retret的操作就相当于pop eip(*),所以esp指针向上移一格,然后代码回到第15行的那条指令
leaveleave指令相当于movl %ebp,%esp; popl %ebp;
ret回到第23行指令继续执行
addl$4, %eax
leaveret
执行完以上所有代码,我们可以看到堆栈又回到了最初的状态。
三、总结
通过以上逐条指令的分析来理解C语言函数的执行过程,能够加深我们对计算机C语言等高级语言的理解,同时对以后学习用户空间虚拟地址空间打下了基础。
四、实验截图
阅读全文
0 0
- 反汇编一个简单的C程序
- 反汇编一个简单的C程序
- 反汇编一个简单的C程序
- 反汇编一个简单的C程序
- 反汇编一个简单的C
- 反汇编一个简单的C程序,分析汇编代码
- 一个简单C程序的编译及反汇编
- 反汇编一个简单的C程序并分析
- 反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
- 一个简单函数的反汇编
- 一个简单函数的反汇编
- 一段简单的C反汇编
- C main的反汇编简单介绍
- Linux内核分析-反汇编一个简单的C程序并简单分析
- MOOC课程《Linux内核分析》——反汇编一个简单的C程序
- Linux内核分析学习_Week1_反汇编一个简单的C程序
- Linux内核分析一:反汇编一个简单的C程序
- 第1节 反汇编一个简单的C程序【Linux内核分析】
- PAT 1027打印沙漏
- 有了Docker的程序猿们就能开启“上帝视角”?
- Spring Cloud Stream 多通道创建
- 脚本语言和其他一些编程语言的区别
- Mysql 常用基本命令(2)
- 反汇编一个简单的C
- nginx的安装与基础配置
- HDU 1028 Ignatius and the Princess III
- Java内存模型
- HDU 1069 Monkey and Banana(DP)
- I/O重定向
- [LeetCode]513. Find Bottom Left Tree Value
- Linux sed命令
- YoucompleteMe安装