c语言程序变汇编,实践!C语言是怎么变成汇编的

本文作者通过实例解析了一段C语言程序如何编译为汇编,揭示了函数调用、栈帧管理和数据传递的底层细节,探讨了计算机执行流程和C语言单返回值限制的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

“郭孟琦 + 原创作品转载请注明优快云博客 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”

在大学计算机组成原理一课中学习各种汇编语言跟C语言的关系,同时在单片机接口技术中也学习了C51的汇编语言,在一些MCU调试中也看到了反汇编的内容。但是从来没亲自实践一下C语言是怎么变成汇编的过程以及他们之间的对应关系。作为作业今天就在这里写下我的发现吧。

按照要求这是一段很简单的c语言程序

0818b9ca8b590ca3270a3433284dd417.png

进行编译生成汇编文件

0818b9ca8b590ca3270a3433284dd417.png

生成的main.s文件 已经把多余的命令删除了(gvim好像确实没vim好用。。。)

0818b9ca8b590ca3270a3433284dd417.png

一开始是这样的 空栈

ebp!esp!

程序从main标签处运行,开始push,mov后(我用ebp!和esp!来表示实际的ebp esp所指向的位置吧,表示起来好麻烦 ebp(main)是指向0那个位置的ebp 就是表格最上边那个位置)

ebp!esp!ebp(main) 到了subl esp减4 向下移动一个字节 并且把立即数233存到了esp指向的位置(间接寻址?)

ebp!ebp(main)

esp! 233 当执行call f时 eip会被push

ebp!ebp(main)

233

esp!eip(main) 接下来看f标签

在push 和movl后 ebp(f)是指向第二行那个ebp

ebp(main)

233

eip(main)

esp!ebp!ebp(f) 同样esp在减4后向下移动1个地址

ebp(main)

233

eip(main)

ebp!ebp(f)

esp! 接下来因为栈空间向下生长,变址寻址向上加8也就是向上2个位置(就是233)存入eax

接下来要把eax的内容存入esp指向的位置就成了

ebp(main)

233

eip(main)

ebp!ebp(f)

esp!233 又一次的Call

ebp(main)

233

eip(main)

ebp!ebp(f)

233

esp!eip(f) 进入g标签,前两句类似(其实就是存储原来ebp的位置将ebp指向新的位置),变址寻址向上加8也就是向上2个位置(就是233)存入eax

ebp(main)

233

eip(main)

ebp(f)

233

eip(f)

ebp!esp!ebp(g) 然后666加上eax里的内容也就是c语言中的 “x +666”啦 到这里函数的嵌套总算是完事了开始一层层恢复,首先是popl ebp,ebp指向f 中的ebp位置了 同时 esp也会加4向上移动

ebp(main)

233

eip(main)

ebp!ebp(f)

233

esp!eip(f)

ebp(g) 然后ret相当于 pop eip程序回到 刚才 eip(f)的那个位置啦

ebp(main)

233

eip(main)

ebp!ebp(f)

esp!233

eip(f)

ebp(g) leave实际上是

mov %ebp %esp

pop %ebp

也就是将上一级的栈恢复回来(有个问题为什么在g里没有leave? 我认为popl %ebp就ok了 因为当时后序操作并未改变esp,esp和ebp指向同一位置 就没必要mov %ebp %esp 了可能就被优化掉了。)

要注意mov后pop操作又再一次改变了esp指向的位置

ebp!ebp(main)

233

esp!eip(main)

ebp(f)

233

eip(f)

ebp(g)

我们继续走ret

ebp!ebp(main)

esp!233

eip(main)

ebp(f)

233

eip(f)

ebp(g) 别忘了结果一直在存着eax,现在再加1 就是c语言里 的f(233)+1

最后leave恢复之前的 ebp和esp

ebp!esp!

ebp(main)

233

eip(main)

ebp(f)

233

eip(f)

ebp(g)  跟刚开始是不是一样了!

那么到现在为止,计算机是如何工作的?

我认为计算机的工作方式就是执行一系列指令,在其中当我们只用高级语言中的“函数调用”等需要跳转时计算机总会先保存现在的状态然后再处理完成后再依次恢复之前的状态,同时需要“带回去”的数据另存在其他地方比如:eax。此外我终于明白为什么C语言只能有一个返回值了。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值