通过汇编一个简单的C程序,分析汇编代码理解计算机工作原理

2019-02-27 14:09:15 浏览数 (1)

源程序

代码语言:javascript复制
int g(int x)
{
   		return x 5;
}

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

int main(void)
{
   		return f(7) 2;
}

编译命令

代码语言:javascript复制
gcc -S -o main.s main.c -m32
  • 将原程序编译成汇编指令,其中-m32是将其编译成32位下的汇编。
  • 将汇编文件中用于链接过程的代码删除,得到下面汇编代码

汇编代码

代码语言:javascript复制
1 g:
2	pushl	�p
3	movl	%esp, �p
4	movl	8(�p), �x
5	addl	$5, �x
6	popl	�p
7	ret
8 f:
9	pushl	�p
10	movl	%esp, �p
11	subl	$4, %esp
12	movl	8(�p), �x
13	movl	�x, (%esp)
14	call	g
15	leave
16	ret
17 main:
18	pushl	�p 
19	movl	%esp, �p  
20	subl	$4, %esp   
21	movl	$7, (%esp)
22	call	f
23	addl	$2, �x
24	leave
25	ret

分析汇编程序

  首先从main函数开始分析,18行将ebp推入栈中,19行中将esp的值赋给ebp(左边值赋给右边),20行开辟4个字节(32位)的栈空间给后面的局部变量7。函数传递传递参数的方式有三种:堆栈方式寄存器方式、以及通过全局变量进行隐含参数的传递。这里是利用堆栈传递参数,堆栈是一种“后进先出”的存储区,栈顶指针ESP指向堆栈中第一个可用的数据项。21行传入7,22行然后调用f函数,call指令可以看成是执行了

代码语言:javascript复制
push %eip(保存23行指令地址)  
movl $9 %eip  

  此时的堆栈情况为:

  主要是保存23行的地址,并跳转到第9行执行。第9行开始又重新开辟了一段堆栈,12行取的是[ebp 8](栈地址是从高地址向低地址生长)的值,即7,然后把7赋给eax,13行把eax赋值给esp,这里实际上将7保存在当前的esp。14行调用g函数。call指令可以看成是执行了

代码语言:javascript复制
pushl %eip (保存15行指令地址)  
movl $2 %eip 

  跳转到第2行执行,开辟一段栈空间,4行取[ebp 8]的值给eax,即7,5行执行7 5=12,把结果存在了eax。   此时的堆栈情况为:

  6行pop出当前的ebp,7行执行ret指令,实际上是:

代码语言:javascript复制
popl %eip  
movl $15 %eip  

  跳转到15行执行leave指令,相当于:

代码语言:javascript复制
movl �p %esp    
popl �p  

  此时f函数的栈空间已经被释放了,此时ebp指向main函数调用f函数之前的栈底,16行的ret使程序跳转到23行执行,eax保存着之前的12,此时再将eax 12=14。然后执行leave和ret指令释放main函数的栈空间。

0 人点赞