简单C程序生成的汇编代码分析

时间:2022-01-25 01:10:09

首先给出完整的C代码:

int g(int x)
{
return x+11;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(8)+1;
}

 

使用命令:gcc –S –o hw001.s hw001.c -m32

对应生成的IA32汇编代码如图所示:

简单C程序生成的汇编代码分析简单C程序生成的汇编代码分析简单C程序生成的汇编代码分析

暂不分析以“.”开头的行,得到程序如下:

g:
pushl %ebp
movl %esp ,%ebp
movl
8(%ebp) ,%eax
addl $
11 ,%eax
popl %ebp
ret
f:
pushl %ebp
movl %esp ,%ebp
subl $
4 ,%esp
movl
8(%ebp) ,%eax
movl %eax ,(%esp)
call g
leave
ret
main:
pushl %ebp
movl %esp ,%ebp
subl $
4 ,%esp
movl $
8 ,(%esp)
call f
addl $
1 ,%eax
leave
ret

 

 

接下来逐行分析汇编代码,主要分析堆栈指针的变化情况:

1明确代码中用到的寄存器的默认功能eax:储存函数返回值。ebp:帧指针,储存堆栈的栈底位置esp:栈指针,储存堆栈的栈顶位置2假设main函数被调用之前,堆栈的栈底对应内存地址为100,栈顶对应内存地址为96,分别存放在ebp和esp内,并假设栈生长方向为内存的低字节方向。3从main函数的入口“main:”开始,
  • pushl %ebp
等价于  subl  $4    ,%esp             movl %ebp , %esp将esp指向下一个空位置,并将当前栈底位置入栈 ,根据假设有,ebp值为100,esp = 92,
  • movl %esp ,%ebp
此时ebp = esp = 92
这两行代码会在每一个函数的起始部分出现,功能是将之前函数的堆栈压入栈底,在其上重新开辟一个新的堆栈,新栈的栈底在92。
  • subl $4 ,%esp
  • movl $8 ,(%esp)
这两行代码将8入栈,相当于pushl $8。此时esp为88。
  • call f
这行代码相当于pushl %eipmovl  f,%eip   @此处的f应该为label f 的地址,即 函数f的入口地址esp为84,接下来程序跳转到f:之后开始执行。
  • pushl %ebp
  • movl %esp ,%ebp
同上,此时有ebp = esp = 80。
  • subl $4 ,%esp
  • movl 8(%ebp) ,%eax
  • movl %eax ,(%esp)
这三行代码将内存地址88处的值8写入eax中。再把esp指向位置76的值写为8。
  • call g
这行代码相当于pushl %eipmovl g,%eip   @此处的g应该为label g 的地址,即 函数f的入口地址。esp为72,接下来程序跳转到g:之后开始执行。
  • pushl %ebp
  • movl %esp ,%ebp
同上,此时有ebp = esp = 68。
  • movl 8(%ebp) ,%eax
  • addl $11 ,%eax
将76位置的值写入eax,再把eax值加11,eax值为19
  • popl %ebp
把当前栈顶值出栈,写入ebp中。即把原ebp值80写回ebp,将esp+4,此时,ebp=80,esp=72。
  • ret
代码相当于popl %eip,即movl (%esp)  ,%eipaddl  $4,         %esp有esp = 76。
  • leave
返回到f中执行代码leave。leave相当于movl %ebp,%esppopl %ebp此时ebp = 92,esp =84。
  • ret
代码相当于popl %eip,即movl (%esp)  ,%eipaddl  $4,         %esp此时ebp = 92,esp = 88。
  • addl $1 ,%eax
返回到main中继续执行,此时eax值为20
  • leave
相当于movl %ebp,%esppopl %ebp此时ebp = 100,esp =96。
  • ret
代码相当于popl %eip,即movl (%esp)  ,%eipaddl  $4,         %esp程序返回到调用main的函数中继续执行。堆栈内容如下表所示:简单C程序生成的汇编代码分析

 简单C程序生成的汇编代码分析

 

 

 

 

by昆仑雪狐

原创作品转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000