程序的机器级表示

原创 2017年04月29日 09:25:40

2017年4月趁着临近毕业时间比较充裕,就买了一本深入理解计算机系统(第三版),这本书的第二版之前浅浅的读过一遍只对里面的编译与链接章节印象深刻,其他章节对我来说完全陌生,我深知这本书的好,于是重新拾起这本书。为了加深自己的记忆就开始写博客记录自己的读书笔记。

第三章 程序的机器级表示

  • gcc4.8 引入-Og选项,使得生成的代码更符合原始程序的结构。

  • 传送类指令的两个操作数不能指向内存位置。

  • 任何更新低位4字节的指令都会把高位字节设置为0,例如: 通过movl将立即数移动到目的寄存器中会将寄存器的高四位设置为0。

  • cltq指令没有操作数,该指令的含义是将%eax作为源,%rax作为符号扩展结果的目的地。

  • leaq指令是用来加载有效地址的,但是通常被用来进行简单的算术操作。

  • cqto指令不需要操作数,直接将%rax中的符号位并将其复制到%rdx的所有位中。

  • 基于控制的条件转移 vs 基于数据的条件转移

    基于控制的条件转移当条件满足时程序沿着一条执行路径走,否则走另外一条执行路径,这种机制简单而通用,但是在现代处理器上可能会非常低效,一种替代策略就是使用基于数据的条件转移,这种方法计算一个条件操作的两种结果,然后再根据条件是否满足从中取一个。这样就可以简单的使用条件传送指令实现了,条件传送指令更符合现代处理器的特性。例如: cmovge指令

  • 在现代处理器下为什么基于控制的条件转移没有基于数据的条件转移性能好?

    基于控制的条件转移导致处理器无法并行的执行条件后面的指令,需要进行指令流的预测,预先执行预测的指令,如果预测成功了,那么事半功倍,如果预测失败了就需要丢弃已经执行的指令结果,然后重新执行新的指令,当预测的准确率不高的情况下会导致性能下降,而基于数据的条件转移就不会出现这种情况。

  • 位操作判断一个数的二进制中存在奇数还是偶数个1

    long func(unsigned long x) {
    long val = 0;
    while(x) {
      val ^= x;
      x >>= 1;
    }
    return x & 0x1;
    }
  • 分支预测错误的处罚

    1. 假设预测错误的概率是p
    2. 如果没有预测错误的情况下,代码的执行时间为T-OK
    3. 预测错误的处罚为T-MP

    执行代码的平均时间如下:

    T-AVG = (1-p)T-OK + p(T-OK + T-MP)

  • 寄存器使用惯例,分为两类,一类是被调用者保存寄存器,另外一类是调用者保存寄存器

    1. %rbx%rbp、 和%r12~%r15 被调用者保存寄存器。被调用的函数在使用这些寄存器之前需要先保存这些寄存器的值。
    2. 所有其他的寄存器,除了栈指针%rsp,都分类为调用者寄存器。也就是任何函数都可以修改它,可以理解为P在这些寄存器里面存放了数据,然后调用Q,Q是可以随便修改这些寄存器的,所以P有责任在调用之前将这些数据保存起来。
  • 数据对齐机制

    ​ 对于大多数x86-64指令来说,保存数据对齐是能够提高效率,但是不会影响程序的行为,另一方面如果数据没有对齐某些型号的Intel和AMD处理器对于实现多媒体操纵的SSE指令,就无法正确执行了。此外地址对齐还有益于提高内存系统的性能,减少CPU读取内存数据的周期。

  • 缓冲区溢出攻击

    ​ 因为局部变量是存放在堆栈上的,而堆栈上还存放了返回地址,别有用心的人可以通过溢出局部变量的存储空间,将恶意代码的指令地址覆盖掉保存在栈上的返回地址,从而执行一些恶意的代码。或者是直接将一些恶意代码的二进制通过溢出局部变量的存储空间使得这些代码保存在堆栈上被执行。现代的编译器实现了很多机制,以避免遭受这样的攻击,限制入侵者通过缓冲区溢出攻击获得系统控制的方式。

    1. 栈随机化属于地址空间布局随机化简称为ASLR

      ​ 通过将栈的位置在程序每次运行时都有变化,实现的方式可以是在程序开始时预先在栈上分配一段0~N字节之间的随即大笑的空间。

    2. 堆栈保护机制

      ​ 在栈帧中任何局部缓冲区与栈状态之间存储一个特殊的金丝雀(canary)值,在恢复寄存器状态和从函数返回的时候都会去检查这个金丝雀值是否被改变了,如果被改变了程序就会异常终止。(gcc 的-fno-stack-protector选项)

    3. 限制可执行代码的存储区域

      ​ 限制哪些内存区域能够存放可执行代码,在典型的程序中,只有保存编译器产生的代码的那部分内存才需要可执行的,其他部分可以被限制为只允许读和写。

版权声明:本文为博主原创文章,未经博主允许不得转载。

程序的机器级表示——《深入理解计算机系统》

机器级代码 计算机系统使用了多种不同形式的抽象,利用更简单的抽象模型来隐藏实现的细节。 对于机器级编程来说,其中两种抽象尤为重要: 1、指令集体系结构(Instruction set a...
  • yang_yulei
  • yang_yulei
  • 2014年03月18日 22:51
  • 4923

51单片机查表指令的用法

51单片机具有两条查表指令,用于从 ROM 中读出预存的数据:    MOVC A, @A + PC    MOVC A, @A + DPTR其中前一条指令的用法,比较难,使用的时候,需要...
  • baidu_33836580
  • baidu_33836580
  • 2016年01月25日 11:45
  • 3142

计算机组成原理课设——我自己亲手写了机器指令和微指令

前言:2014年12月,大二上学期,计算机组成原理课程设计,我当年亲手写了一些机器指令,甚至设计出了一些微指令(扩充指令集,写到控制存储器里面),想想都觉得我当年好厉害。。。...
  • u013390476
  • u013390476
  • 2016年01月19日 17:58
  • 3642

中文版-深入理解计算机系统讲义 第三章 程序的机器级表示

  • 2017年08月23日 15:07
  • 4.97MB
  • 下载

第三章 程序的机器级表示

1、历史观点   2、程序编码 命令gcc---GCC C、C++编译器。是Linux上默认的编译器。 gcc命令调用一系列程序,将源代码转化成可执行代码: Ø  首先,C预处理器扩展源代码...
  • yvhqbat
  • yvhqbat
  • 2015年10月11日 11:43
  • 309

程序的机器级表示(2)--IA32汇编代码

IA32的整数寄存器一个IA32中央处理单元(CPU)包含一组8个储存32位值的寄存器。这些寄存器储存整数数据和指针。...
  • qq_33102061
  • qq_33102061
  • 2017年08月01日 09:21
  • 173

深入理解计算机系统(笔记):程序的机器级表示

分析高级语言编译后生成的汇编语言。 1. 程序编码 运行如下命令得到C语言的汇编代码: unix> gcc -O1 -S code.c gcc -c选项编译源文件生产目标文件code.o: u...
  • navyhu
  • navyhu
  • 2015年06月04日 22:10
  • 603

《深入理解计算机系统》第3章 程序的机器级表示

要点一:数据格式(c语言在IA32中表示的大小) 要点二:IA32的整数寄存器 要点三:操作数指示符 要点五:数据传送指令 要点六:算术和逻辑操作 要点七:特殊的算术操作...
  • jxwaxyk
  • jxwaxyk
  • 2012年04月18日 19:52
  • 429

<深入理解计算机系统> 通过程序的机器级表示来理解函数栈

C源码: void swap(int *a,int *b) { int c; c = *a; *a = *b; *b = c; } int main(void) { ...
  • zy416548283
  • zy416548283
  • 2015年03月03日 17:50
  • 2751

六星经典CSAPP-笔记(3)程序的机器级表示

1.前言IA32机器码以及汇编代码都与原始的C代码有很大不同,因为一些状态对于C程序员来说是隐藏的。例如包含下一条要执行代码的内存位置的程序指针(program counter or PC)以及8个寄...
  • dc_726
  • dc_726
  • 2015年01月17日 10:22
  • 4047
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:程序的机器级表示
举报原因:
原因补充:

(最多只允许输入30个字)