程序的机器级表示

原创 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. 限制可执行代码的存储区域

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

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

相关文章推荐

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

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

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

IA32的整数寄存器一个IA32中央处理单元(CPU)包含一组8个储存32位值的寄存器。这些寄存器储存整数数据和指针。...

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

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

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

C源码: void swap(int *a,int *b) { int c; c = *a; *a = *b; *b = c; } int main(void) { ...

CSAPP读书笔记——程序的机器级表示之寄存器分布与mov指令集

IA32整数寄存器的划分IA32(Inter Architecture 32-bit)处理器中有88个3232位的寄存器(register)用来存储整型和指针(浮点数由单独的寄存器处理)。这就是88个...

chap3: 程序的机器级表示

3.2、程序编码      1、对机器级编程而言,两种抽象尤为重要:1)指令集体系结构(Instruction set architecture,ISA;2)虚拟地址;      2、程序存储器包含:...

程序的机器级表示(IA32,AT&T,一)

前言我们编写出来的代码只是单纯的ASCII码字符而已。其文本是不能在机器上运行的。机器只能识别机器码,也就是所谓的位串。由01组成的流控制电路的翻转,最后组成了具有逻辑意义的代码。那么,我们很容易发现...

计算机系统学习2:程序的机器级表示之函数调用

函数调用的解释

程序的机器级表示<CSAPP>

1.一个IA32 CPU包含一组8个存储32位值的寄存器。这些寄存器用来存储整数数据和指针。 " style="border:0px; max-width:100%; display:block...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:程序的机器级表示
举报原因:
原因补充:

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