Linux内核分析之计算机是如何工作的
一、计算机工作原理
本周实验主要是反汇编C代码,生成汇编程序。冯·诺依曼理论的要点是:数字计算机的数制采用二进制,计算机应该按照程序顺序执行。人们把冯·诺依曼的这个理论称为冯·诺依曼体系结构。CPU通过总线从内存中读取一条条程序,根据程序的内容执行具体的步骤。CPU在读取指令时,通过寄存器IP来指向下一条指令(如果是32位系统,则为EIP),CPU的寄存器分为通用寄存器、段寄存器、状态寄存器。可以用一张图来说明

进程是一个可执行程序的实例。从内核角度看,进程由用户内存空间和一系列内核数据结构组成,其中用户内存空间包含了程序代码及代码使用的变量,而内核数据结构用于维护进程状态信息。每个进程分配的内存由很多部分组成。当计算机在运行时,先从内存中取出第一条指令,通过控制器的译码,按指令的要求,从存储器中取出数据进行指定的运算和逻辑操作等加工,然后再按地址把结果送到内存中去。接下来,再取出第二条指令,在控制器的指挥下完成规定操作。依此进行下去。直至遇到停止指令。
计算机的寻址方式老师介绍了以下几种:
movl %eax,%edx edx=eax 寄存器寻址
movl $0x123,%edx edx=0x123 立即寻址
movl 0x123,%edx edx=*(int32_t*)0x123 直接寻址
movl (%ebx),%edx edx=*(int32_t*)ebx 间接寻址
movl 4(%ebx),%edx edx=*(int32_t*)(ebx+4) 变址寻址
二、实验内容
对于简单C语言程序main.c
int g(int x)
{
return x + 4;
}
int f(int x)
{
return g(x);
} int main(void)
{
return f(5) + 1;
}

使用如下命令编译成汇编代码,然后删除汇编代码中用于链接的辅助信息:
gcc –S –o main.s main.c -m32
得到的文件保存在main.s中
g:
pushl %ebp
movl %esp, %ebp
movl (%ebp), %eax
addl $4, %eax
popl %ebp
ret f:
pushl %ebp
movl %esp, %ebp
subl $, %esp
movl (%ebp), %eax
movl %eax, (%esp)
call add
leave
ret main:
pushl %ebp
movl %esp, %ebp
subl $, %esp
movl $5, (%esp)
call f
addl $1, %eax
leave
ret

处理后的汇编代码为:

设空栈如下:
从main开始执行,以下为逐句解释:
最开始的时候ebp和esp都指向标号0的位置
pushl %ebp :ebp入栈,保存当前ebp0,esp-4指向标号1
movl %esp, %ebp :将ebp指向标号1
subl $, %esp :esp-,指向标号2
movl $5, (%esp) :esp指向的栈中标号2对应的地方存储5
call sec :将eip()入栈,esp-4指向标号3,跳转至f执行
接下来执行f中的代码:
pushl %ebp :将ebp()入栈,esp-4指向标号4
movl %esp, %ebp :ebp指向标号4
subl $, %esp :esp-,指向标号5
movl (%ebp), %eax :将ebp指向的地址加八对应地址中的数据放入eax,即标号2对应存储数据5,所以(eax)=5
movl %eax, (%esp) :把eax放入esp对应位置,即栈中标号5对应位置
call g :将eip()入栈,esp-4指向标号6,跳转至g执行
接下来执行g中的代码:
pushl %ebp :ebp()入栈,esp-4指向标号7
movl %esp, %ebp :ebp指向标号7
movl (%ebp), %eax :ebp+8位置中的数据赋给eax,即标号5位置,(eax)=5
addl $4, %eax :eax中数据+4,即5+4=9
popl %ebp :ebp()出栈,即ebp指向标号4,esp+4指向标号6
ret :eip()出栈,esp+4指向标号5,跳转至第16行继续执行
接下来又回到f中继续执行:
leave :把ebp赋给esp,即esp指向标号4,ebp()出栈,esp+4指向标号3,ebp指向标号1
ret :eip()出栈,esp+4指向标号2,跳转至第25行继续执行
接下来回到main中继续执行:
addl $1, %eax :eax中的数据+1,即9+1=10
leave :把ebp赋给esp,即esp指向标号1,ebp()出栈,ebp指向标号0,esp+4指向标号0
ret :此时栈已经空了,恢复最开始的状态,运行结束,最后的结果保存在eax中,为10。
三、 堆栈变化分析
程序从main.s第17行开始运行,CPU的IP寄存器指向汇编代码的第18行,假设堆栈在内存中的地址分别为0,1,2,3……堆栈基指针寄存器(EBP)和堆栈顶指针寄存器(ESP)均指向堆栈段0处。第18~21行首先为main函数开辟新的内存区域,之后将传的参数5入栈,此时堆栈段如下所示:

然后程序调用call 函数,将IP入栈,IP指向代码第9行f处。
在f函数的代码处,首先为f函数开辟新的内存区域,接着将传入的参数5赋值给EAX,并将EAX入栈

程序在此调用call进入g函数。在g函数中,同样先是开辟内存空间,然后将参数传给EAX,并将EAX的值加上4。之后将EBP出栈,并调用ret命令。此时IP重新指向f函数call之后的命令。

之后就是不断的调用leave与ret命令,跳出当前的内存区域,回到上一级函数的内存区域中
ret指令执行后函数g调用完毕,返回。leave指令用于释放一个子例程的栈帧,等价与以下两条指令:
- movl %ebp, %esp
- popl %ebp
并将EAX的值加4,直到跳出main函数,至此程序结束
四、总结
通过本次课程的学习,我掌握了存储计算机工作模型和汇编的基础知识。计算机的基本原理是存贮程序和程序控制。预先要把指挥计算机如何进行操作的指令序列(称为程序)和原始数据通过输入设备输送到计算机内存贮器中。每一条指令中明确规定了计算机从哪个地址取数,进行什么操作,然后送到什么地址去等步骤。
其中,掌握冯·诺依曼体系结构是理解计算机工作原理的要点。按照冯·诺依曼存储程序的原理,计算机在执行程序时须先将要执行的相关程序和数据放入内存储器中,在执行程序时CPU根据当前程序指针寄存器的内容取出指令并执行指令,然后再取出下一条指令并执行,如此循环下去直到程序结束指令时才停止执行。其工作过程就是不断地取指令和执行指令的过程,最后将计算的结果放入指令指定的存储器地址中。
在课程中提到了很多操作系统的内容由于知识结构,我比较欠缺,今后我会加强这方面的知识储备。
刘帅
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
Linux内核分析之计算机是如何工作的的更多相关文章
- Linux内核分析之操作系统是如何工作的
在本周的课程中,孟老师主要讲解了操作系统是如何工作的,我根据自己的理解写了这篇博客,请各位小伙伴多多指正. 一.知识点总结 1. 三个法宝 存储程序计算机:所有计算机基础性的逻辑框架. 堆栈:高级语言 ...
- linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作
一.实验 使用gcc –S –o main.s main.c -m32 命令编译成汇编代码,如下代码中的数字请自行修改以防与他人雷同 int g(int x) { return x + 3; } in ...
- 《Linux内核分析》第一周 计算机是如何工作的?
刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK ONE(2. ...
- LInux内核分析——计算机是如何工作的进行
万子惠 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 " 实 ...
- Linux内核分析第一周学习总结:计算机是如何工作的?
韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.冯诺依曼体系 ...
- 《Linux内核分析》第一周笔记 计算机是如何工作的
一.计算机是如何工作的? 1.存储程序计算机工作模型 1)冯诺依曼体系结构 学习研究计算机的基本概念.就是指存储程序计算机.所有的有计算功能的电子设备小到计算器,大到超级计算机核心部分都可以用这种体系 ...
- 《Linux内核分析》第一周学习小结 计算机是如何工作的?
<Linux内核分析>第一周.计算机是如何工作的? 20135204 郝智宇 一.存储程序计算机工作模型 1. 冯诺依曼体系结构: 数字计算机的数制采用二进制:计算机应该按照程 ...
- 《Linux内核分析》 之 计算机是如何工作的
[李行之原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] <Linux内 ...
- linux内核分析--计算机是如何工作的
实验部分 使用gcc -S -o main.s main.c -m32命令将源代码编译成汇编代码. 源代码如下: int g(int x) { return x + 9; } int f(int x) ...
随机推荐
- invalid END header (bad central directory offset) 异常解决方法
今天版本升级时,一个ear包在传到aix下,weblogic后启动出现 invalid END header (bad central directory offset) 后来才发下是文件传输中出现了 ...
- Angularjs-Dirty Checking
Angularjs实现了数据双向绑定,就像下面这样: <!doctype html> <htnl ng-app> <head> <script src=&qu ...
- Libevent 定时器
先摘一点网上的介绍 libevent是一个事件触发的网络库,适用于windows.linux.bsd等多种平台,内部使用select.epoll.kqueue等系统调用管理事件机制.著名分布式缓存软件 ...
- C++学习基础三——迭代器基础
迭代器分为两种:一种是iterator,另一种是const_iterator.两者都可进行访问容器中的元素,不同之处是:(1)const_iterator类型只能用于读取容器内的元素,不能更改其值:而 ...
- 自己练习读取写入txt
读取文件中的内容生成一个list,然后修改list后再写会该文件文件中的格式是:AA,BB,CC,DDblist = []for line in open('a.txt'): blist.extend ...
- java并发编程_CountDownLanch(倒计数锁存器)应用场景
使用介绍: 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在 ...
- JStorm第一个程序WordCount详解
一.Strom基本知识(回顾) 1,首先明确Storm各个组件的作用,包括Nimbus,Supervisor,Spout,Bolt,Task,Worker,Tuple nimbus是整个storm任务 ...
- Python_sklearn机器学习库学习笔记(一)_一元回归
一.引入相关库 %matplotlib inline import matplotlib.pyplot as plt from matplotlib.font_manager import FontP ...
- [整理]PCB阻抗控制
之前一直听说PCB设计中信号完整性及阻抗方面的要求,但是本人对此还是有很多的不了解,每次和别人讨论到这里后就不知道该怎么继续就这个问题交谈下去.正巧最近手头有一点工作有这方面的一些需求,就拿来花了一点 ...
- Selenium2+python自动化4-Pycharm使用
前言 在写脚本之前,先要找个顺手的写脚本工具.python是一门解释性编程语言,所以一般把写python的工具叫解释器.写python脚本的工具很多,小编这里就不一一列举的,只要自己用着顺手就可以的, ...