zoukankan      html  css  js  c++  java
  • 《Linux内核分析》第一周 计算机是如何工作的?

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

    WEEK ONE(2.22——2.28)计算机是如何工作的?

    【基本的汇编程序工作原理】

    SECTION 1 存储程序计算机

    1.1冯诺依曼体系结构:即具有存储程序的计算机体系结构

    目前大多数拥有计算和存储功能的设备(智能手机、平板、计算机等)其核心构造均为冯诺依曼体系结构

    1. 从硬件来看
      • CPU与内存通过主线连接,CPU上的IP(可能是16、32、64位)总指向内存的某一块区域;IP指向的CS(代码段)也在内存中;CPU总是执行IP指向的指令。
    2. 从软件来看
      • API(应用程序编程接口,与编程人员)与ABI(程序与CPU的借口界面) 是两个比较重要的软件接口

    1.2 课件4/21

    关于ABI:指令编码;指令中涉及的寄存器布局;大多数指令可以直接访问内存

    1.3 课件5/21

    (E代表32位系统)EIP在CPU执行完一条指令之后自加一(自动加一条指令,而不是一个字节或是32位),当然也可以被其它指令,如CALL,RET等修改

    SECTION 2 x86汇编基础

    2.1 x86(32位)的寄存器中,低16位作为16位register

    2.2 关于堆栈段寄存器

    EBP(堆栈基址寄存器);ESP(堆栈顶指针寄存器)。上述两个寄存器较为频繁地使用于汇编程序中

    2.3 关于代码段寄存器

    CPU实际取指令的时候通过cs:eip来描述

    2.4 64位CPU

    其实与32位在核心机制上差别不大,64位的机器中,寄存器以RXX表示

    2.5 常见汇编指令

    1. 后缀的b,w,l,q分别代表8,16,32,64位
    2. 以%标识的寄存器寻址不与内存“打交道”
    3. 直接寻址&立即数寻址
      1. movl $0x123,%eax —— %eax=0x123
      2. movl 0x123,%eax —— 立即数是以$开头的十六进制数值。直接访问指定的内存地址(0x123)中的数据然后赋给%eax
    4. 变址寻址

      movl 4(%ebx),%edx//edx = *(inet_32 *)(ebx+4),即ebx的值加4之后作为一个地址,将其指向的数据赋给%edx
      
    5. 大多数指令都可以直接访问内存地址
    6. Linux使用的A&T汇编格式与Intel汇编略有不同
    7. 几条重要的汇编指令

    2.6汇编小程序练习

    以上图中的片段1和3为例完成堆栈变化图:

     

    SECTION 3 汇编一个简单的C程序

    3.1 将C代码编译成汇编代码

    • 将代码在实验楼环境中(64位)保存之后,建议使用 -m32将其编译为32位的汇编代码
    • 具体如下:

       gcc -S -o main.s main.c -m32
      
    • 关于leave指令
      • leave指令与enter指令一起相当于两条宏指令
      • enter指令相当于在原来的堆栈上再建一个新的空堆栈【因为将栈底指针%ebp挪到和栈顶指针相同的位置了】
      • leave指令与enter相反,相当于撤销函数调用堆栈【把栈顶指针提上来,则撤消了该栈】
    • 函数调用堆栈是由逻辑上多个堆栈叠加起来的。
    • 函数的返回值默认用%eax存储,然后返回给上一级函数。

    3.2 练习2

    【分析】

    1. 从main函数的堆栈变化开始看,可以发现堆栈中填充了8;猜想8可能是主函数传给g(x)的参数;
    2. 调到g后,可以看到先将8传给了%eax;然后再加上了8,紧接着弹栈;猜想应该是x+8;
    3. 主函数又减去了8.这样得到的是x+8-8;
    4. 函数应该如下:

      int g(int x)
      {
          return x+8;
      }
      int main(void)
      {
          return g(8)-8;
      }

    实验部分

    • 实验步骤

    • 实验代码

    • 代码汇编结果

    add:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    addl    $6, %eax
    popl    %ebp
    ret
    f:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    add
    leave
    ret
    main:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    $6, (%esp)
    call    f
    addl    $1, %eax
    leave
    ret
    
    • 分析(堆栈变化过程图解)

    总结

    理解“计算机是如何工作的”?

    【理解】

    我认为,首先需要明确的一点就是:计算机并不“聪明”;相反的是,计算机十分“笨拙”。越是简洁通用的规则(哪怕代价是需要很多的重复计算)越能够让计算机充分发挥其优势——见字面意思,即“计算(compute)”。

    1. 计算机的硬件设施部分,就如第一讲中讲到的那样,除了核心CPU之外,还有寄存器、高速缓存、主存乃至外存这样种类繁多的存储设备。存储设备(这也是冯 诺依曼体系结构的一个重要支点)根本目的就是为CPU服务,存储各种各样的、区分轻重缓急的数据;
    2. 有了上面的硬件基础,计算机的工作过程就集中在了CPU和为其传输数据的地址总线上。各种各样的I/O设备传来的信息、计算机内置的各种程序(比如一些规则、保障性机制)甚至于网络上传播的木马病毒……形形色色的data与code集合都要整合成一条条指令——还是那句话,计算机很“笨拙”,它(CPU)执行的最底层的操作就是N种指令而已;
    3. 计算机的这些指令的执行过程就如同汇编程序中显示的那样,CPU兢兢业业地往各种寄存器中填入数据、跳转或者撤销、释放……这一系列的基本操作(当然还要有硬件配合)在极短的时间完成,未来还会将时间进一步缩短。然后,不可思议的事情就这么发生了:我们可以在计算机中进行闪电般的运算、将各种媒体形式传输到网络上……然而,这些的基础都将追溯到这些0101串中。
  • 相关阅读:
    Debian 9 更换源
    MySqlDataAdapter.Fill() 报异常‘给定关键字不在字典中’的解决方案
    阿里云函数计算 .NET Core 初体验
    TimeSpan 的 Milliseconds 和 TotalMilliseconds 有啥区别?
    使用 gitee 托管你的 go 模块
    markdown的css样式(自己写的)
    markdown的流程图实现和代码语法着色
    Python元组与字典详解
    centos7的防火墙(firewalld)
    centos7 安装java和tomcat9
  • 原文地址:https://www.cnblogs.com/lwr-/p/5211491.html
Copyright © 2011-2022 走看看