Linux第一周学习总结——计算机是如何工作的
第一周学习总结——计算机是如何工作的
作者:刘浩晨
一、存储程序计算机工作模型
冯诺依曼体系结构:核心思想为存储程序计算机。两个层面:
(1)硬件的角度(计算机主板):一个CPU,一块内存,之间有总线连接。CPU内部有一个IP计算器,IP指向内存中的指令,并依次加一执行;
(2)另一个层面,程序员的角度:存储程序计算机工作模型(如下图)
解释:CPU抽象为for循环,总是执行下一条指令,内存保存指令和数据,CPU来解释和执行这些指令。
API:应用程序编程接口(程序员与计算机的接口界面)
ABI:二进制接口,指令编码(程序员与CPU的接口界面)
二、X86汇编
1.X86CPU的寄存器
(1)通用寄存器
堆栈基指针和堆栈顶指针较为重要。
(2)段寄存器:
其中代码段和堆栈段用的较多。CPU在实际取指令时根据cs:eip来准确定位一个指令。
(3)标志寄存器
标志寄存器可以标识当前的一些状态。
2.计算机的汇编指令
(1)movl指令:
-
寄存器寻址,寄存器模式,以%开头的寄存器标示符。不和内存打交道,eax赋值给edx;
-
立即寻址,把立即数直接放在寄存器,立即数是以$开头的数值;
-
直接寻址,直接访问一个指定的内存地址的数据;
-
间接寻址:将寄存器的值作为一个内存地址来访问内存;
-
变址寻址:在间接寻址之时改变寄存器的数值。
注意:AT&T汇编格式与Intel汇编格式略有不同,Linux内核使用的是AT&T汇编格式。
(2)其他指令
堆栈是向下增长的,有一个基址ebp指向堆栈栈底
-
pushl 压栈,esp减4,把eax放入esp内存位置
-
popl 出栈,从堆栈栈顶取32位放到寄存器eax里面,有两个动作:首先间接寻址,把栈顶数值放到eax里面,再把栈顶加4。
-
call 函数调用,把当前的eip压栈,给eip赋新值;
注意:*是指这些指令是伪指令,程序员不能直接修改这些,即eip寄存器不能被直接修改,只能通过特殊指令间接修改。
三、汇编一个简单的C程序分析其汇编指令执行过程
1.练习:分析一段汇编代码
2.将C代码编译成汇编代码
1.函数调用堆栈是由逻辑上多个堆栈叠加起来的
2.函数的返回值默认使用eax寄存器存储返回给上一级函数
3.使用命令编译成汇编代码:gcc –S –o main.s main.c -m32
堆栈变化:
四、实验内容——反汇编一个简单的C程序
简单C程序:
汇编代码:
分析汇编代码的工作过程中堆栈的变化:
首先开始入栈,从main函数开始,按照下图画出流程进行执行:
此时eax=8+8=16。下一条指令popl %ebp开始出栈:
五、学习总结体会
由于上学期进行过初步的Linux学习,所以这周内容并不困难。老师讲了一些基本的概念,然后通过一个完整的简单C程序的汇编代码实例讲解,让我们更加清楚计算机中指令执行时堆栈的变化,这也有助于我们理解计算机到底是如何工作的。我觉得计算机是非常精细的,但通过这周课程的学习,简单来说在它工作过程中,按照冯诺依曼原理的话就是存储和程序。指令序列就为程序,这些指令和数据等预先存储在内存中,工作时,CPU从内存中取出指令,从存储器中取出数据进行指定的运算和逻辑操作等加工,再按地址把结果送到内存中去。再取出下一条指令完成相应操作,直至完成停止。现在我还只能理解一些小的简单的程序,对于更加复杂更加实用的东西还需要进一步学习。老师讲解的方式和内容都很好,我相信这应该会是一次很棒的学习体验过程。
参考资料:
《Linux内核分析》MOOC课程 http://mooc.study.163.com/course/USTC-1000029000
《深入理解计算机系统》