存储程序计算机的工作原理简介

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/RonnyYoung/article/details/57076131

作者:奋斗的白杨(杨延生)

注:原创作品转载请注明出处

《Linux内核分析》 MOOC课程http://mooc.study.163.com/course/USTC-1000029000


1.  冯诺依曼结构计算机

早期的计算机(例如第一台通用计算机ENIAC)采用的程序与数据分享的形式进行计算,数据保存在穿孔纸带上,而对于数据的控制则通过开关和连线来控制。计算机内部采用十进制,这样就大大增加了计算机电路复杂性。

冯诺依曼参与了刚才所说ENIAC的研发,并提出了自己的修改意见,写成了EDVAC的草案中,草案中第一次提出了存储程序的思想,也就是说把程序与数据不加区分的对待,都存储在存储器中,并首次把计算机分别了5大重要组成部件。

  • 控制器
  • 运算器
  • 存储器
  • 输入设备
  • 输出设备

2. 存储程序计算机执行程序的过程

计算硬件设计保证了CPU会一条一条的执行存储器中的指令(对应了一条汇编代码),那么每一条指令的执行过程都包括了4个步骤:

取址->译码->执行->回写

取址:就是将指令的内容从存储器取回到CPU,在存储器中的位置是写在IP(指令指针寄存器,也叫PC)中,取回的指令放在IR(指令寄存器)中。

译码:CPU中的译码把IR中的二进制指令解析出一系列的控制信号。

执行:CPU根据译码的结果,进行电路控制,将相关的数据都放在对应的寄存器中,然后计算器(ALU)开始计算。

回写:CPU将计算结果写到指定的寄存器中。

3. 示例程序的汇编代码分析

源代码:
int g(int x) {
    return x + 42;
}

int f(int x) {
    return g(x);
}

int main(void) {
    return  f(42) + 1;
}

在Intel X86_64位上编译为32位下的汇编代码
gcc -S -o main.s main.c -m32

编译后的代码去掉.开头的部分(用于链接的信息),得到如下部分:
g:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        addl    $42, %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    $42, (%esp)
        call    f
        addl    $1, %eax
        leave
        ret

下面分析程序在执行过程中进程栈的变化情况(主要是ebp和esp的变化)

假设进程栈顶底的内存地址为0x100。栈由高地址向低地址增长,开始ebp和esp都为0x10,即都指向栈底,栈内为空。
在执行程序过程中栈和寄存器的变化如下图:


4. 总结

计算机以进程的概念处理程序,程序中的代码与数据被不加区分的以二进制的形式存储在存储器中(存储的位置由存储器决定)。CPU可以自动的逐条的执行程序的代码,相关的数据以及指令跳转信息都通过进程栈来存储。

函数间的跳转主要需要做的事为:1。记录之前eip到栈内,方便回头继续执行。2. 进入到新的函数中,要保存原来的函数的栈基址,然后有了自己新的栈基址。

函数返回时,就会从栈中读出原来进入函数时保存的信息,包括了外部函数的栈基址,以及继续执行的指令的位置。


实验楼实验截图


没有更多推荐了,返回首页