说到计算机,大家都知道现代计算机都是由冯诺依曼体系结构组成的,也就是储存程序计算机。让我先从它的工作模型说起。
冯诺依曼体系结构由运算器、控制器、存储器、输入设备和输出设备组成,其中指令与数据同时存放在储存区中。它们工作时的状态如图所示:
我们的程序运行时,一般都是操作系统当做程序与硬件之间的“中间人”,而应用程序与操作系统之间的交互,则依赖于ABI(Application Binary Interface)。当然,我的水平还远不到读写二进制机器码的程度,自然也不会深究这个ABI。
下面,我们来对一个简单的C程序进行汇编,C语言源代码如下:
int func1(x)
{
return x + 10;
}
int func2(x)
{
return func1(x);
}
int main(int argc, char * argv[])
{
return func2(20) + 8;
}
笔者使用了实验楼的Linux环境来实现获得程序编译所得的X86(32位)汇编程序,链接在此: https://www.shiyanlou.com/courses/195
使用gcc即可,命令如下:
gcc –S –o main.s main.c -m32
其中,-S表示在程序编译期间,在生成汇编代码后停止,-o参数输出汇编代码文件main.s,而-m32自然就是生成32位的汇编代码。
其中以.开头的命令都是作为链接的命令,我们把以.开头的行全部删除,得到汇编代码如下:
func1:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $10, %eax
popl %ebp
ret
func2:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
call func1
leave
ret
main:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $20, (%esp)
call func2
addl $8, %eax
leave
ret
至此,我们就完成了对程序的汇编,然后我们来看看程序的执行过程:
在堆栈增增减减的过程中,计算机也不断的取指令、执行指令,完成对程序的执行。
Author : 陈政 / arc001
原创作品转载请注明出处 《Linux操作系统分析》MOOC课程