汇编指令执行过程分析

一、编写C程序,并编译

// main.c
int g(int x)
{
    return x + 1;
}

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

int main(void)
{
    return f(1) + 1;
}
$ gcc –S –o main.s main.c -m32

编译后

删除以“.”开头的辅助信息后

g:
      pushl %ebp 
      movl  %esp, %ebp
      movl  8(%ebp), %eax
      addl  $1, %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  $1, (%esp)
      call  f
      addl  $1, %eax
      leave
      ret

二、下面分析过程

1.首先执行main函数,

pushl %ebp保存调用函数的基址(ebp中)到栈中,压栈操作此时esp自动下移一个地址空间(4个字节)
movl %esp, %ebp将esp的内容放到ebp中,设置ebp为当前被调用函数的基址指针,即当前栈顶
subl $4, %espesp下移一个地址空间(4个字节),为当前函数分配1个栈空间(4个字节)用于存储局部变量
movl $1, (%esp)将1放到esp当前指向的位置
call f=pushl %eip(*) movl f %eip(*)将此时eip中的值(下一条指令addl $1, %eax)压栈,然后将f函数的地址放到eip中,这样程序转而执行f函数。

2.执行f函数

pushl %ebp保存调用函数的基址(ebp中)到栈中,压栈操作此时esp自动下移一个地址空间(4个字节)
movl %esp, %ebp将esp的内容放到ebp中,设置ebp为当前被调用函数的基址指针,即当前栈顶
subl $4, %espesp下移一个地址空间(4个字节),为当前函数分配1个栈空间(4个字节)用于存储局部变量
movl 8(%ebp), %eaxebp中的地址上移2个(8个字节)地址空间的内容放到eax中,也就是将数字1放到eax中
movl %eax, (%esp)将eax中的内容放到esp当前指向的位置
call g =pushl %eip(*) movl g %eip(*)将此时eip中的值(下一条指令leave)压栈,然后将g函数的地址放到eip中,这样程序转而执行g函数。

3.执行g函数

pushl %ebp 保存调用函数的基址(ebp中)到栈中,压栈操作此时esp自动下移一个地址空间(4个字节)
movl %esp, %ebp将esp的内容放到ebp中,设置ebp为当前被调用函数的基址指针,即当前栈顶
movl 8(%ebp), %eax将ebp上移2个地址空间的内容放到eax中,就是数字1
addl $1, %eax将1与eax中的数相加,也就是2放到eax中
popl %ebp 恢复ebp为调用函数基址
ret =popl %eip(*)就是f函数中的leave

4.返回执行f函数

leave=movl %ebp,%esp popl %ebp将ebp中的那内容放到esp,将回复ebp为调用函数基址
ret=popl %eip(*)就是main函数中的addl $1, %eax

5.返回执行main函数

addl $1, %eax将1与eax中的内容相加,也就是1+2=3,将3放到eax中
leave=movl %ebp,%esp popl %ebp将ebp中的那内容放到esp,将回复ebp为调用函数基址
ret返回main函数之前的堆栈

posted @ 2020-10-13 20:10  逐北  阅读(312)  评论(0编辑  收藏  举报