云课堂-linux内核分析:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

时间:2021-10-25 00:51:24

陈绍斌 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

=。=第一次弄博客,完全不会啊。请务必指导我。

C程序代码:

int g(int x)
{
	return x + 3;
}

int f(int x)
{
	return g(x);
}

int main(void)
{
	return f(4) + 1;
}

编译环境:

Ubuntu 14.04,GCC 4.8,GDB 7.7 因为是64位的环境,所以和32位的寄存器名和一些操作有所区别。。。

编译命令:
gcc -o main -g main.c
生成目标文件和调试信息

启动GDB:
gdb ./main
列出源码:
layout src 
l
列出汇编指令:
Ctrl + x,再按2, 显示汇编指令

云课堂-linux内核分析:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的


云课堂-linux内核分析:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的


依次分析汇编指令:
1.    0x400513 <main>            push   %rbp                             将main函数栈底rbp内存地址压栈                     
2.    0x400514 <main+1>        mov    %rsp,%rbp                    将栈底指向栈顶(相当于新建一个栈)
3.    0x400517 <main+4>        mov    $0x4,%edi                     将数值4存入寄存器edi                   
4.    0x40051c <main+9>        callq  0x4004fc <f>                 跳转到函数f
5.    0x4004fc <f>                    push   %rbp                             将函数f栈底内存地址压栈
6.    0x4004fd <f+1>               mov    %rsp,%rbp                    将函数f栈底指向栈顶(相当于新建一个栈)                                      
7.    0x400500 <f+4>              sub    $0x8,%rsp                      将栈顶内存地址值减8                                   
8.    0x400504 <f+8>              mov    %edi,-0x4(%rbp)           (为什么是减4)  int是32位缘故?
9.    0x400507 <f+11>            mov    -0x4(%rbp),%eax          上面两步实现将数值4写入寄存器eax                                
10.  0x40050a <f+14>            mov    %eax,%edi                     将eax中存储的数值4写入寄存器edi                            
11.  0x40050c <f+16>            callq  0x4004ed <g>                跳转到函数g
12.  0x4004ed <g>                  push   %rbp                             将函数g栈底内存地址压栈                                 
13.  0x4004ee <g+1>              mov    %rsp,%rbp                    将函数g栈底指向栈顶(相当于新建一个栈)                                     
14.  0x4004f1 <g+4>              mov    %edi,-0x4(%rbp)                                                     
15.  0x4004f4 <g+7>              mov    -0x4(%rbp),%eax          上面两步实现将数值4写入寄存器eax                                           
16.  0x4004f7 <g+10>            add    $0x3,%eax                     寄存器eax加3                                      
17.  0x4004fa <g+13>            pop    %rbp                              出栈                                  
18.  0x4004fb <g+14>            retq                                          返回,栈顶地址写入eip
19.  0x400511 <f+21>            leaveq                                       rsp指向栈底,rbp出栈                      
20.  0x400512 <f+22>            retq                                          返回
21.  0x400521 <main+14>      add    $0x1,%eax                      寄存器eax加3                     
22.  0x400524 <main+17>      pop    %rbp                              出栈
23.  0x400525 <main+18>      retq                                          返回

体会:
应该把栈画出来,把操作用gif动图形式表现出来才直观啊= =。。。文字叙述到自己都快混乱了- -。。。
个人理解是进行函数调用时,把当前执行的指令的下一条地址压栈,再把旧函数的栈底移向栈顶,把调用函数的入口写入栈中。