- 实验一:反汇编一个简单的C程序
- 实验过程:
- 1、编写简单C语言程序
- 2、调用命令对C语言程序进行反汇编 *** 作
- 3、使用vim查看反汇编main.s文件
- 4、反汇编文件main.s分析
- main
- f函数
- g函数
- 总结
gcc –S –o main.s main.c -m32
可以看到反汇编成功,创建了main.s文件
对应c语言文件中的三个函数:int g()、int f()、int main(),反汇编代码同样也分为g、f和main部分。
在分析前首先对汇编语言部分做个笔记
其中有四个寄存器:
Name | Value |
---|---|
ebp | 堆栈基指针,该指针永远指向系统栈最上面一个栈帧的底部 |
esp | 堆栈底指针,该指针永远指向系统栈最上面一个栈帧的栈顶 |
eip | 指令指针 |
eax | 累加寄存器 |
以下将从过程来分析,首先是main函数
mainmain:
pushl %ebp
movl %esp, %ebp
subl , %esp
movl , (%esp)
call f
addl , %eax
leave
ret
main函数作为入口函数,所以eip的值为11
pushl %ebp
(1)将堆栈基指针压入栈中
movl %esp, %ebp
(2)将堆栈底指针赋值给堆栈基指针
subl , %esp
(3)堆栈顶指针地址减去立即数4,相当于指针向下移动一个单元
movl , (%esp)
(4)将立即数5放置在堆栈顶指针对应地址的内存上
call f
(5)调用f函数,call f整体 *** 作可以分解为,存储当前命令指针位置,并跳跃到f函数所在处
push eip
movl f, eip
此时来到了f函数的部分(具体在f函数细讲)
(6)回到main函数部分后,累加寄存器加上立即数2
addl , %eax
(7)此 *** 作将esp和ebp指针都指向main函数的最初位置
leave
(8)回到更上一层的堆栈
ret
f函数
f:
pushl %ebp
movl %esp, %ebp
subl , %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
call g
leave
ret
在main函数调用f函数后
(1)将堆栈基指针压入栈中
pushl %ebp
(2)将堆栈顶指针的值赋值给堆栈基指针,使得堆栈基指针指向堆栈顶指针指向的地方
movl %esp, %ebp
(3)堆栈顶指针减去立即数4,使得该指针指向下一个存储单元
subl , %esp
(4)将堆栈底指针所指向的上两个单元(变址寻址)对应的内容存入累加器中
movl 8(%ebp), %eax
(5)将累加器中的内容赋值给堆栈顶指针对应的内存中
movl %eax, (%esp)
(6)和main函数中的call f一样调用g函数,整体也可以分解成push和movl两个步骤
call g
(7)此 *** 作将esp和ebp指针都指向f函数的最初位置
leave
(8)回到更上一层的堆栈
ret
g函数
g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl , %eax
popl %ebp
ret
(1)将堆栈底指针压入堆栈
pushl %ebp
(2)将此时的堆栈顶指针赋值给堆栈底指针
movl %esp, %ebp
(3)将堆栈底指所对应上两个单元的内容赋值给累加寄存器,此时eax=5
movl 8(%ebp), %eax
(4)累加寄存器加上立即数7,此时eax=12
addl , %eax
(5)堆栈底指针出栈,堆栈顶指针指向上个单元内存
popl %ebp
(6)回到上一层堆栈
ret
总结
从这一份简单的C语言程序反汇编所得到的代码中,可以基本看到在汇编语言层面,计算机运作主要围绕esp、ebp、eip和eax几个寄存器展开。例如简单的函数调在汇编层面就需要先压栈存储当前指令位置,赋值指令位置,执行完函数后d出堆栈,是的指令寄存器的值回到原来的点。再比如,esp和ebp在汇编中运用的更加频繁,这两个指针与当前指令执行时密切相关,由于地址在存储时是递减的,所以能看到很多词esp-4得到下一个单元地址的 *** 作。总的来说汇编有很多理解空间,帮助学习计算机的底层知识。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)