通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
于佳心 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
计算机是如何工作的?
计算机的工作的基础冯诺依曼体系结构,即存储程序计算机。
这里涉及到两个重要的接口,一个是API,程序员与计算机的接口,另一个是ABI,程序与CPU的接口。
程序员通过编程语言下达指令,指令则通过汇编被翻译成计算机语言,使计算机能够明白你的意思,进而执行。
汇编语言中的指令有好多种,大多数指令可以直接访问内存。
下面就是一个将C代码编译成汇编代码的具体操作过程
这个程序的返回值为21
检验一下,可以运行(没有输出)
输入给出的语句编译成汇编代码,生成.s文件
长长的汇编代码出炉
据说前面带“.”的语句表示链接
☝☝☝☝☝
精简版汇编代码
可见这个程序分为三部分:主函数,子函数f,子函数的子函数g
在程序开始运行之前,系统中有一个空堆栈,指向栈底的ebp和指向栈顶的esp都指向0的位置,eip存储cpu要读取的指令的地址,每运行一步它就自动+1,eax是返回值。
需要注意的是,下面图片中的图片0,1,2,3...并不是真正的地址值,只是为了方便才这样写,按理说应该是以4为单位向下逐级递减的,比如2016,2012,2008...
程序从main开始运行:
执行到call f这一步时,eip指向了f,接下来将从f开始运行:
call g之后开始运行g中的指令:
ret就相当于popl %eip,eip跳转到了15,开始执行f中未进行的指令,leave可拆分成如下图中的两步(指令后面的 l 忘记写了。。。)
eip跳转到了23,执行main中未执行的指令(最后一个ret可能涉及到这个程序之外的内容,不予考虑)
程序运行完毕,返回值正确
堆栈的功能是暂时存放数据和地址,观察图片我发现,堆栈的形态先是不断的向下伸长,长到一定程度就往回收缩,最后的形态与它的原始形态相同。
总结
通过这次试验,我更加深入的理解了计算机是如何工作的。首先我们要把一段程序送给计算机(也有可能是计算机自带的程序),我们要明确的告诉计算机从哪里取需要的数值,如何操作,将操作后得数值放到哪里。然后,计算机会按照程序的顺序一步一步将指令取出,翻译成自己能懂的语言,再进行操作,运行完一条指令,再取下一条指令,这便是冯诺依曼原理。寄存器在执行指令过程中起到了很大的作用。操作中需要用到的数据都存储在堆栈里,通过两个地址寄存器在适当的时候调用。eip则控制程序的执行顺序,何时应该顺序执行,何时应该跳转。eax用于保存返回值。
虽然一步一步画图分析很麻烦,但是分析完还是很有成就感的,虽然看视频觉得自己已经很懂了,真正分析起来还是会出现问题,会无从下手,又要翻出视频来求助,完整的分析一遍后发现这才是真正记住了,果然记忆光靠看不行,还要靠实践。
假期的最后几天忽然有了学习任务,好在并不是很难,学到的内容大多都接触过,但是由于记忆力太差,和新学的没什么区别,以前学的时候就没怎么弄懂,现在终于弄懂了。
希望大家假期最后几天都玩得开心~