c语言运行汇编程序,C语言程序执行从汇编角度详解

本课题来源:网易云课堂《Linux内核分析》

地址:https://mooc.study.163.com/learn/1000029000?tid=2403023011&_trace_c_p_k2_=b007fad39e354f55af484d41391c5783#/learn/announce

关键字:栈,函数,调用,汇编,寄存器

概述:C语言程序介于汇编语言和高级语言中间面,拥有直接操纵内存入口,同时拥有高级语言易读性。这里我们将通过汇编角度探索程序执行开始、结尾、中间入栈出栈操作。

正文:

原始C程序

57707204def0afa6f249e838e66404a4.png

对应汇编程序

8dce78f9b822b30b29752a42ed4a9dac.png32位机器对应汇编指令

一、基础知识补充:

1.1、32位机汇编指令:movl、subl、addl、pushl、popl、call、leave、ret

movl %ebp, %esp 将ebp中内容放置到esp中。

subl $4, %esp 寄存器esp值减少4。

addl $1, %eax 寄存器eax中值增加1。

popl %ebp 栈顶内容保存到ebp中,之后esp寄存器数值加4。

pushl %ebp 将ebp中内容入栈,之后esp寄存器值减4。

call f 先将eip指向地址入栈(call f 下一条指令位置),之后eip指向f地址位置。

pushl %eip

movl f , %eip

leave 将ebp中的内容移动到esp中去,之后出栈内容到ebp中。

movl %ebp, %esp

popl %ebp

ret 出栈内容到eip中。

popl %eip

1.2 、相关寄存器:ebp、esp、eip

ebp 段寄存器,保存栈基址。

esp 保存当前栈顶地址。

eip 存放在执行指令的下一条指令地址。 cs:eip唯一确定一条指令。

1.3、栈

4f2bc0e71aa98cdaa28e67a6b6b16cb4.png栈结构

新增数据入栈,栈顶指针向下移动,寄存器esp中的值减少4。数据出栈,栈顶指针向上移动,寄存器esp中的值增加4。

二、剖析汇编程序

2.1、 程序入栈

程序找到main函数入口,即cs:eip指向位置

pushl %ebp

9b0cc3c0095502281a0b523277614cec.pngebp入栈

movl %esp,%ebp

d057a3e1d8a390d7fb68f97e0dba161c.pngesp值赋予ebp

subl $4 ,%esp

624ac86adfef190f5548f5d5a110fc09.png栈顶指针向下移动一个存储单元

movl $5, (%esp)

29bcfb1c68b4f5728c570c3c9de1d253.png数据存放到esp所指向位置

call f :2条指令集合,pushl %eip 、 movl f , %eip

9bf16376e1bea17ca760d00dd5eb1e8a.pngeip值入栈(call f下一条指令地址)

2e18192e08ee4aed6aa23ce0d15ab3da.png对eip重新赋值,指向f函数入口地址

a38c9936653958a5765e994c4916d36f.png将先前ebp所指向地址入栈(main)

b8aa9e40594df2480974eff03e080ad5.png将ebp指向新的函数入口(f)

subl$4, %esp

b0287109b3488bf4c03f0225183741e2.pngesp指针向下移动一个位置

movl 8(%ebp),%eax

5b2d54948856bbcf77e20126f99d1cee.pngeax接收函数返回值5

movl %eax,(%esp)

4fe81f2030bf278db0a84664d3c15cee.pngmain函数传递参数到f

call g

pushl %eip

a4b285826d889343cd58acf37efa5b5c.pngcall g下一跳指令地址入栈 15

movl f,%eip

964728e4b05069e895a5b28dbe1ab6b5.pngeip指向将要执行的指令即 g函数位置

pushl%ebp

movl%esp, %ebp

movl8(%ebp), %eax

addl $6,%eax

以上4条执行完,即函数入栈全部结束

85fb2f49370457be42da22e948149524.png

2.2、程序出栈

popl %ebp

fdb93f84c46229494716806e2e73b546.png返回f函数入口处

ret

cc06ff67b805c5201a0658adbb430e33.png下一条执行指令位置为leave

leave

a21d79363b4417629ea94fc91ea1964b.png栈顶指向ebp位置

弹出f函数

da1358280570e57323401c943c8b6364.pngebp指向main函数入口位置

ret

ea0091941f62f3845ab37557edf1bdf3.png执行指令转到main程序

addl $1,%eax

最终返回值位11+1=12

leave

6ce9c9dbb556e17a7b4bc494c1aa90a4.png

popl %ebp

d7836db19fa993b9918b84d1ce5e1a98.png程序栈基址返回系统掉用入口

ret

a3b9872ea6cdd5ebbc236d656388e1d7.png执行程序返回到系统调用下一条指令

至此函数生命周期全部完成

三、总结与展望

第一次对于函数入栈出栈有了大体认识,了解了为什么程序会有生命周期,函数会有生命周期。巧妙的设计方法都有待学习。

本例程序中仍有很多地方认识不是特别到位,留下足迹,记录自己成为大牛历程。

举报/反馈

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值