韩玉琪 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、冯诺依曼体系结构:存储程序计算机

1. 从硬件角度

	 	 总线
CPU ============ 内存 - CPU上的IP总指向内存的某一块区域,CPU执行其所指向的指令。

2. 从程序员角度(软件)

内存保存指令和数据,CPU解释执行
  • 接口

    • API:应用程序编程接口,程序员<->计算机
    • ABI:应用程序二进制接口,程序<->CPU

二、汇编基础

1. 寄存器

  • 通用寄存器
通用寄存器
16bit 32bit
AX eax 累加器
BX ebx 基址寄存器
CX ecx 计数寄存器
DX edx 数据寄存器
BP ebp 堆栈基址指针
SI esi 变址寄存器
DI edi 变址寄存器
SP esp 堆栈顶指针
  • 段寄存器
段寄存器
CS 代码段
BS 数据段
ES 附加段
SS 堆栈段
FS 附加段
GS 附加段
  • CPU实际取指令的时候根据cs:eip来准确定位一个指令

2. 几种寻址方式

  • 寄存器寻址(register)

      例:movl %eax,%edx  <=>  edx=eax
  • 立即数寻址(immediate)

      例:movl $0x123,%edx  <=>  edx=0x123
  • 直接寻址(direct)

      例:movl 0x123,%edx  <=>  edx=*(int32_t*)0x123
  • 间接寻址(indirect)

      例:movl (%ebx),%edx  <=>  edx=*(int32_t*)ebx
  • 变址寻址(displaced)

      例:movl 4(%ebx),%edx  <=>  edx=*(int32_t*)(ebx+4)
  • 注:Linux内核使用A&T汇编格式(另有Intel汇编格式)

3. 常见指令

  • pushl %eax:

      subl $4,%esp
    movl %eax,(%esp)
  • popl %eax:

      movl (%esp),%eax
    addl $4,%esp
  • call 0x12345:

      pushl %eip (*)
    movl $0x12345,%eip (*)
  • ret:

      popl %eip (*)
  • enter:

      pushl %ebp
    movl %esp,%ebp
  • leave

      movl %ebp,%esp
    popl %ebp
  • 注:由于eip不能被程序员直接修改,所以(*)不能直接使用。

  • 函数调用堆栈是由逻辑上多个堆栈叠加起来的。

  • ebp和esp这两个寄存器总是指向堆栈的栈底和栈顶,这里所说的是相对的概念。

  • 函数返回值默认存储在%eax寄存器中。

二、汇编代码的分析

1. main.c代码

2. 汇编代码

gcc -S -o main.S main.c -m32

-S:仅汇编
-m32:生成32位的指令格式

3. 分析

初始状态:从main开始执行

  • 假设起始地址为2016,%ebp、%esp都指向2016。

第18行:pushl %ebp

  • 相当于先执行 subl $4,%esp => esp指向2012;
  • 然后 movl %ebp,(%esp) => 将ebp的值放在esp所指向位置,即把“2016”放在2012的位置上。
  • ebp = 2016,esp = 2012

第19行:movl %esp,%ebp

  • ebp指向与esp相同的位置2012上。
  • ebp = 2012,esp = 2012

第20行:subl $4,%esp

  • esp减4,即向下移动到位置2008上。
  • ebp = 2012,esp = 2008

第21行:movl $2,(%esp)

  • 把立即数2放在esp所在位置2008上。
  • ebp = 2012,esp = 2008

第22行:call fun

  • 调用函数fun
  • push %eip => esp向下移到位置2004,把eip(下一条指令所在,即第23行)放在该位置上,然后将fun函数所在赋给eip,执行fun函数的指令。
  • ebp = 2012,esp = 2004

第8行:跳转到fun的初始状态

  • ebp = 2012,esp = 2004

第9行:push %ebp

  • ebp = 2012,esp = 2000

第10行:movl %esp,%ebp

  • ebp = 2000,esp = 2000

第11行:subl $4,%esp

  • ebp = 2000,esp = 1996

第12行:movl 8(%ebp),%eax

第13行:movl %eax,(%esp)

  • 将(ebp+8)即位置2008存放的值通过eax放在esp位置1996上
  • eax = 2
  • ebp = 2000,esp = 1996

第14行:call add

  • ebp = 2000,esp = 1992

第1行:跳转到add的初始状态

  • ebp = 2000,esp = 1992

第2行:pushl %ebp

  • ebp = 2000,esp = 1988

第3行:movl %esp,%ebp

  • ebp = 1988,esp = 1988

第4行:movl 8(%ebp),%eax

第5行:addl $7,%eax

  • 将(ebp+8)即位置1996处存放的值赋给eax;
  • 此时,eax = 2,然后加7,eax = 9。
  • ebp = 1988,esp = 1988

第6行:popl %ebp

  • 相当于先movl (%esp),%ebp => 把esp位置1988存放的值赋给ebp,ebp指向2000。
  • 然后addl $4,%esp => 将esp上移到位置1992。
  • ebp = 2000,esp = 1992

第7行:ret

  • 相当于popl %eip
  • esp上移到位置1996,指令执行第15行。
  • ebp = 2000,esp = 1996

第15行:leave

  • 相当于先movl %ebp,%esp => 将esp指向ebp,即位置2000。
  • 然后popl %ebp => ebp指向位置2000存储的值,即位置2012处,esp指向位置2004。
  • ebp = 2012,esp = 2004

第16行:ret

  • ebp = 2012,esp = 2008

第23行:addl $3,%eax

  • eax加3,eax = 12
  • ebp = 2012,esp = 2008

第24行:leave

  • ebp = 2016,esp = 2016

第25行:ret

  • 回到执行main之前的位置

寄存器内容变化

三、总结:关于计算机是如何工作的

  1. 复杂又简单的计算机:计算机能实现许多看起来很复杂的功能,计算和处理大量的数据,但是,它实现这些复杂功能是不断地重复大量既定的简单的操作。
  2. 程序:我们一般做的,是告诉计算机操作的步骤、输入的数据是什么、处理后的结果如何存储。然后,计算机会尽可能忠实地按照程序的顺序将每一个操作步骤的指令取出,变成机器语言,通过软硬件协同工作。
  3. 汇编语言:汇编语言其实也是机器语言的一种翻译。现在编译器功能优化的比较强大,学习汇编语言真正用的时候并不多,但它是我们分析处理问题的一种角度。能够看懂汇编语句,在分析程序真正执行的流程、单步调试程序的方面都是有帮助的。

Linux内核分析第一周学习总结:计算机是如何工作的?的更多相关文章

  1. LINUX内核分析第一周学习总结——计算机是如何工作的

    LINUX内核分析第一周学习总结——计算机是如何工作的 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/ ...

  2. Linux内核分析第一周学习博客 --- 通过反汇编方式学习计算机工作过程

    Linux内核分析第一周学习博客 通过反汇编方式学习计算机工作过程 总结: 通过这次对一个简单C程序的反汇编学习,我了解到计算机在实际工作工程中要涉及大量的跳转指针操作.计算机通常是顺序执行一条一条的 ...

  3. linux内核分析第一周学习笔记

    linux内核分析第一周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  4. LINUX内核分析第二周学习总结——操作系统是如何工作的

    LINUX内核分析第二周学习总结——操作系统是如何工作的 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...

  5. 20135320赵瀚青LINUX内核分析第一周学习笔记

    赵瀚青原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.概述 第一周的学习内容主 ...

  6. Linux内核分析——第一周学习笔记20135308

    第一周 计算机是如何工作的 第一节 存储程序计算机工作模型 1.冯·诺依曼结构模型:冯·诺依曼结构也称普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构.程序指令存储地址和数据存储 ...

  7. Linux内核分析——第一周学习笔记

    20135313吴子怡.北京电子科技学院 chapter 1 知识点梳理 第一节 存储程序计算机工作模型 1.冯诺依曼体系结构:即具有存储程序的计算机体系结构.目前大多数拥有计算和存储功能的设备(智能 ...

  8. Linux内核设计第一周学习总结 计算机如何工作

    北京电子科技学院 20135310陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-100002 ...

  9. Linux第一周学习总结——计算机是如何工作的

    第一周学习总结--计算机是如何工作的 作者:刘浩晨 一.存储程序计算机工作模型 冯诺依曼体系结构:核心思想为存储程序计算机.两个层面: (1)硬件的角度(计算机主板):一个CPU,一块内存,之间有总线 ...

随机推荐

  1. 2015GitWebRTC编译实录15

    各个库编译完成后,整合talkapp,联编时还是碰到了一些问题,主要是lib里的源码文件被错误移走,或者宏定义等有问题的,不一而足 FQ访问https://apprtc.appspot.com/,拿到 ...

  2. 《统计推断(Statistical Inference)》读书笔记——第5章 随机样本的性质

    有了前四章知识的铺垫,第五章进入了统计研究的正题——样本的研究.样本可以说是统计学研究中最基本的对象,样本的数学性质也是最重要的研究课题,统计学的一大任务就是从一大堆样本中提取出有价值的知识,正如对原 ...

  3. 论文笔记之: Person Re-Identification by Multi-Channel Parts-Based CNN with Improved Triplet Loss Function

    Person Re-Identification by Multi-Channel Parts-Based CNN with Improved Triplet Loss Function CVPR 2 ...

  4. Jquery选择器之基本选择器

    id选择器 共同点: text:代表标签之间的文本值 返回值:均为列表 根据给定的ID值匹配一个标签元素,如果id值中有元字符(如 !"#$%&'()*+,./:;<=> ...

  5. C#创建datatable

    Asp.net DataTable添加列和行的方法 方法一: DataTable tblDatas = new DataTable("Datas"); DataColumn dc ...

  6. SQL2005:SQL Server 2005还原数据库时出现“不能选择文件或文件组XXX_log用于此操作的解决办法

    SQL2005 还原数据库失败,提示如下: SQL Server 2005还原数据库时出现“不能选择文件或文件组XXX_log用于此操作的解决办法 出现错误时操作步骤为:右击数据库--->任务- ...

  7. 【xargs使用】查询包含某字符串的所有文件

    在initrd目录下,查找包含"Loading virtio.ko"的所有文件 cd initrd find . | xargs grep "Loading virtio ...

  8. web.config

    参数上传和文件上传大小限制调整,参数上传最大2097151 <system.web> <httpRuntime requestValidationMode="2.0&quo ...

  9. zhuang 定制iOS 7中的导航栏和状态栏

    近期,跟大多数开发者一样,我也正忙于对程序进行升级以适配iOS 7.最新的iOS 7外观上有大量的改动.从开发者的角度来看,导航栏和状态栏就发生了明显的变化.状态栏现在是半透明的了,这也就意味着导航栏 ...

  10. 【knowledgebase】如何知道partition数

    对于调优和排错来说,查看一个RDD有多少个partition是非常有用的.常用的查看方法有如下几种: 1.通过SparkUI查看Task执行的partition数 当一个stage执行时,能通过Spa ...