遇到的问题:
汇编代码的理解还不够熟练,需要画图,对照着代码一步一步走。 比如寄存器相关知识: %eax,%后面是寄存器的名称。 %ebx是指这个起存器中存的值是内存地址。 (%ebx)是指这个内存地址所存储的数据。 寄存器寻址:movl %eax,%edx这句指的是把寄存器%eax内容放到%edx中.
实验一:反汇编一个简单的C程序
实验步骤
- 在实验楼环境中进入目录Code(注:进入Code文件是为了保存相关代码文件),创建main.c,并编辑main.c文件,截图如下:
- vim编辑器编辑main.c程序,代码如下:
int g(int x)
{
return x + 3;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(6) + 2;
}
3. 用 gcc 将main.c编译成汇编代码,代码如下:
$ gcc main.c
$ ./a.out
$ echo $?
$ gcc –S –o main.s main.c -m32
查看main.s,源码繁琐,删除以点开头的,剩下就是纯汇编代码: 简化后汇编代码:
实验分析如下:
程序从main 函数开始执行,具体过程如下:
main:
- pushl %ebp,ESP的地址减4即ESP指向标号1,将EBP寄存器的值放到栈顶;
- movl %esp,%ebp,将EBP指向ESP所指的位置即标号1;
- subl $4,%esp,ESP寄存器减4 即ESP指向标号2;
- movl $6,(%esp) ,将立即数6放入到ESP所指向的位置,为即将调用的f函数做准备;
- call f, 把EIP的值23压入栈顶,再将函数f的第一条指令的位置9放到EIP中,ESP指向标号3;
f: - pushl %ebp, ESP指向标号4,将EBP寄存器的值放到栈顶;
- movl %esp,%ebp, 将EBP指向ESP所指的位置即标号4;
- subl $4,%esp,ESP寄存器指向标号5;
- movl $8(%ebp),%eax ,EBP寄存器变址寻址,EBP寄存器的值加8,指向立即数为6的位置,将立即数6放到EAX寄存器中;
- movl %eax,(%esp), 将EAX中存储的立即数6放到ESP所指的位置;
- call g,把EIP的值即15压入栈顶,再将函数g的第一条指令的位置2放到EIP中,ESP指向标号6;
g: - pushl %ebp, ESP指向标号7,将EBP寄存器的值放到栈顶;
- movl %esp,%ebp,将EBP指向ESP所指的位置,并且EIP的值加一,指向8(%ebp),%eax。
- movl 8(%ebp),%eax,EBP寄存器变址寻址,EBP寄存器的值加8,指向立即数为1的位置,将立即数1放到了EAX寄存器中;
- addl $3,%eax,将立即数3加到EAX中,EAX的值即6+3为9;
- popl %ebp,恢复函数f的函数调用堆栈基址EBP寄存器,即EBP指向标号4,ESP指向标号6;
- ret ,将ESP寄存器所指向的栈空间存储单元放到EIP寄存器中,即EIP指向第15行指令,ESP指向标号5;
f: - leave ,撤销函数堆栈,EBP指向标号1,ESP指向标号3;
- ret ,将ESP寄存器所指向的内容放到EIP寄存器中,即EIP指向第23行指令,ESP指向标号2;
main: - add $2,%eax, 把EAX寄存器立即数加2,即9+2为11。EAX存储器是默认存储函数返回值的寄存器;
- leave,撤销函数main的堆栈;
《Linux内核分析》第一章知识
- 冯 诺依曼体系结构:运算器、存储器、控制器、输入设备和输出设备。
- 计算机内部采用二进制表示指令和数据。
- CPU就是执行下一条指令,从内存中取下一条指令来执行。
- ABI接口主要是一些指令的编码。
- 通用寄存器
EAX:累加器 EBX:基地址寄存器 ECX:计数寄存器 EDX:数据寄存器 EBP:堆栈基址针 ESI、EDI:变址寄存器 ESP:堆栈顶指针 - 段寄存器
CS:代码段寄存器,其值为代码段的段值 DS:数据段寄存器,其值为数据段的段值 ES:附加段寄存器,其值为附加段的段值 SS:堆栈段寄存器,其值为堆栈段的段值 FS:附加段寄存器,其值为附加数据段的段值 GS:附加段寄存器,其值为附加数据段的段值 - 最常见的汇编指令是mov指令,movl中的l是指32位。
- %eax,%后面是寄存器的名称。
%ebx是指这个寄存器中存的值是内存地址。 (%ebx)是指这个内存地址所存储的数据。 - 几个重要指令:pushl/pop 压栈/出栈和call/ret 调用函数/返回函数
|