c语言程序中函数执行顺序,从C语言中的函数调用过程理解计算机执行原理

本文是Mooc 课程第一次作业.

姓名:石维康

转载请注明出处.

经过简单的数字修改,需要编译的C语言代码如下:

int g(int x)

{

return x + 2;

}

int f(int x)

{

return g(x);

}

int main(void)

{

return f(5) + 4;

}

编译后生成的汇编代码如下所示:

ea1c268be8e2

Screen Shot 2016-02-27 at 8.02.50 PM.png

生成的完整汇编代码如下:

g:

pushl %ebp

movl %esp, %ebp

movl 8(%ebp), %eax

addl $2, %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 $5, (%esp)

call f

addl $4, %eax

leave

ret

完整截图(对应汇编代码函数):

ea1c268be8e2

汇编代码

与视频中采用相同约定,假设初始esp= ebp =0.

先进入main函数执行到call f后,esp=3,ebp=1,堆栈目前的情况

编号 内容

| --- | --- |

ebp | 1 | 0 |

| --- | --- |

| --- | --- |

| 2 | 5 |

| --- | --- |

| --- | --- |

esp | 3 | 23 |

| --- | --- |

| --- | --- |

| 4 | |

| --- | --- |

进入f函数,执行到call g后,堆栈如下

ebp=4

| --- | --- |

| 1 | 0 |

| --- | --- |

| --- | --- |

| 2 | 5 |

| --- | --- |

| --- | --- |

| 3 | 23 |

| --- | --- |

| --- | --- |

ebp-> | 4 | 1 |

| --- | --- |

| --- | --- |

| 5 | 5 |

| --- | --- |

| --- | --- |

esp-> | 6 | 14 |

| --- | --- |

进入g函数执行运算,执行到addl $2, %eax 这句. eax=5+2=7

| --- | --- |

| 1 | 0 |

| --- | --- |

| --- | --- |

| 2 | 5 |

| --- | --- |

| --- | --- |

| 3 | 23 |

| --- | --- |

| --- | --- |

| 4 | 1 |

| --- | --- |

| --- | --- |

| 5 | 5 |

| --- | --- |

| --- | --- |

| 6 | 15 |

| --- | --- |

| --- | --- |

esp,ebp-> | 7 | 4 |

| --- | --- |

在g函数值中,在eip指向ret语句时(即执行完popl %ebp),堆栈如下:

| --- | --- |

| 1 | 0 |

| --- | --- |

| --- | --- |

| 2 | 5 |

| --- | --- |

| --- | --- |

| 3 | 23 |

| --- | --- |

| --- | --- |

ebp-> | 4 | 1 |

| --- | --- |

| --- | --- |

| 5 | 5 |

| --- | --- |

| --- | --- |

esp-> | 6 | 15 |

| --- | --- |

ret 后 eip=15,堆栈变成如下:

| --- | --- |

| 1 | 0 |

| --- | --- |

| --- | --- |

| 2 | 5 |

| --- | --- |

| --- | --- |

| 3 | 23 |

| --- | --- |

| --- | --- |

ebp-> | 4 | 1 |

| --- | --- |

| --- | --- |

esp-> | 5 | 5 |

| --- | --- |

f中的leave执行完之后:

| --- | --- |

ebp-> | 1 | 0 |

| --- | --- |

| --- | --- |

| 2 | 5 |

| --- | --- |

| --- | --- |

esp-> | 3 | 23 |

| --- | --- |

执行f中的ret后,eip=23,eax=7:

| --- | --- |

ebp-> | 1 | 0 |

| --- | --- |

| --- | --- |

esp-> | 2 | 5 |

| --- | --- |

执行main中的leave后,堆栈如下,eax=11,esp=ebp=0:

ebp,esp-> | --- | --- |

| 1 | 0 |

| --- | --- |

回到初始态.

我对计算机执行程序的理解:

计算机只是机械的从PC指针指向的位置取指令并解析执行.而数据与指令都是以二进制形式进行存储.

在C语言层面上的函数调用与返回的语义,在x86层面上是通过call指令与ret指令来完成.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值