20135202闫佳歆--week1 计算机是如何工作的

计算机是如何工作的

这一周我学习了计算机工作的相关知识。

最基础的,就是冯诺依曼体系结构结构,它最核心的思想是存储程序计算机,要点是:数字计算机的数制采用二进制;计算机应该按照程序顺序执行。

除了思想之外,我还复习了曾经学过的汇编相关的知识,包括操作数的类型,寻址的几种方式,还有一些具体的操作指令。这些指令我是第三次接触了,在我之前做过的一篇学习总结中已经有过详细的论述,这里就不再赘述,列出地址给予参考。

=link

在过往的学习中我了解到,汇编语言是一种机器语言,通过对堆栈,对存储器,对寄存器,等等的操作,来实现一系列的指令。我们日常所使用的诸如c语言这种高级语言,落到具体操作的时候,在计算机的层面,还是依靠汇编语言来执行的,高级语言中简单的一行代码,汇编语言就可能需要很多很多行来逐一实现。这种实现是顺序进行的,通过一些转移指令进行跳转,跳转时又依赖堆栈来保持数据和栈指针。

这种机理,作业中的实验可以很直接的表现出来。

具体实验的步骤,在上学期的课程中已经实践过了,参见上述地址对应总结中最后的作业部分,有实验所用代码,执行语句,精简后的反汇编代码,以及简略的堆栈变化分析。由于当时堆栈分析并不是很详细,所以我重新推演一遍,以求更精准更细致的理解。

我使用的代码(test.c)如下:

#include<stdio.h>
int add(int x)
{
    return x+9;
}

int sec(int x)
{
    return add(x);
}

int main(void)
{
    return sec(15)+9;
}

经过gcc -S -o test.s test.c -m32的指令反汇编后,得到的文件保存在test.s中,精简后得到如下内容:

1    add:
2    	pushl	%ebp
3    	movl	%esp, %ebp
4   	movl	8(%ebp), %eax
5  	    addl	$9, %eax
6   	popl	%ebp
7	    ret
8
9    sec:
10	    pushl	%ebp
11    	movl	%esp, %ebp
12    	subl	$4, %esp
13    	movl	8(%ebp), %eax
14    	movl	%eax, (%esp)
15    	call	add
16    	leave
17    	ret
18    
19    main:
20    	pushl	%ebp
21    	movl	%esp, %ebp
22    	subl	$4, %esp
23    	movl	$15, (%esp)
24    	call	sec
25    	addl	$9, %eax
26    	leave
27    	ret

设空栈如下:

从main开始执行,以下为逐句解释:
最开始的时候ebp和esp都指向标号0的位置

pushl	%ebp    :ebp入栈,保存当前ebp0,esp-4指向标号1
movl	%esp, %ebp  :将ebp指向标号1
subl	$4, %esp    :esp-4,指向标号2
movl	$15, (%esp) :esp指向的栈中标号2对应的地方存储15
call	sec :将eip(25)入栈,esp-4指向标号3,跳转至sec执行

接下来执行sec中的代码:

pushl	%ebp    :将ebp(1)入栈,esp-4指向标号4
movl	%esp, %ebp  :ebp指向标号4
subl	$4, %esp    :esp-4,指向标号5
movl	8(%ebp), %eax   :将ebp指向的地址加八对应地址中的数据放入eax,即标号2对应存储数据15,所以(eax)=15
movl	%eax, (%esp)    :把eax放入esp对应位置,即栈中标号5对应位置
call	add :将eip(16)入栈,esp-4指向标号6,跳转至add执行

接下来执行add中的代码:

pushl	%ebp    :ebp(4)入栈,esp-4指向标号7
movl	%esp, %ebp  :ebp指向标号7
movl	8(%ebp), %eax   :ebp+8位置中的数据赋给eax,即标号5位置,(eax)=15
addl	$9, %eax    :eax中数据+9,即15+9=24
popl	%ebp    :ebp(4)出栈,即ebp指向标号4,esp+4指向标号6
ret :eip(16)出栈,esp+4指向标号5,跳转至第16行继续执行

接下来又回到sec中继续执行:

leave   :把ebp赋给esp,即esp指向标号4,ebp(1)出栈,esp+4指向标号3,ebp指向标号1
ret :eip(25)出栈,esp+4指向标号2,跳转至第25行继续执行

接下来回到main中继续执行:

addl	$9, %eax    :eax中的数据+9,即24+9=33
leave   :把ebp赋给esp,即esp指向标号1,ebp(0)出栈,ebp指向标号0,esp+4指向标号0
ret :此时栈已经空了,恢复最开始的状态,运行结束,最后的结果保存在eax中,为33.

附图三张:

原文地址:https://www.cnblogs.com/20135202yjx/p/5220953.html