Computer Systems A Programmer’s Perspective II (深入理解计算机系统 第二 – 三章 )

1 chapter two: Representing and Manipulating Infomation

信息的表示和处理

1.1 Infomation Storage 信息存储

1.1.1 CONCEPTS
  • byte , 最小的可寻址的存储器单元.
  • virtual memory
  • address , 存储器的每个字节都由一个唯一的数字来标识.
  • virtual address space ,虚拟地址空间 即 所有可能的地址的集合.
  1. 二进制与十六进制的转换 :

    每四位单独转换.

1.1.2 WORDS

word size : 指明整数和指针数据的标准大小 (nominal size) . 字长决定了虚拟地址空间的最大大小.

1.1.3 ENDIAN
  1. little endian
  2. big endian
  3. bi-endian

    example: int x = 0×1234567; x’s address = 0×100 ;

    address 0×100 0×101 0×102 0×103
    big endian 01 23 45 67
    little endian 67 45 23 01
    1. Notice :

      C语言中的typedef声明提供了一种给数据类型命名的方式,可以极大的改善代码的可读性. 如 typedef unsigned char * byte_pointer ;

1.1.4 REPRESENTING STRING

1.1.5 REPRESENTING CODE

1.1.6 INTRODUCTION TO BOOLEAN ALGEBRA (布尔代数)

1.1.7 BIT-LEVEL OPERATIONS IN C
  1. Exclusive-OR (异或)
1.1.8 LOGICAL OPERATIONS IN C (逻辑运算)

1.1.9 SHIFT OPERATIONS IN C (移位运算)

1.2 Integer Representations 整数表示

1.2.1 INTEGER DATA TYPE (NORMAL)
type mix max
char -128 127
unsigned char 0 255
short (int) -32768 32767
unsigned short 0 65535
int -2147483648 2147483647
  1. two’s-complement 补码
  2. ISO C99 中在stdint.h中引入 intN_t和uintN_t ,来标识N位有符号和无符号的整数,保证行为一致性.

1.3 Integer Arithmetic

1.4 Floating Point 浮点数表示

1.5 Summary

1.6 Homework Problems !!!!! hard


2 chapter three: Machine-Level Representation of Programs

程序的机器级表示 计算机执行机器代码,用字节序列编码低级的操作,包括处理数据,管理存储器,读写存储设备上的数据,以及利用网络通信.编译器基于编程语言的原则,目标机器的指令集和操作系统遵循的规则,经过一系列的阶段产生机器代码.

GCC C语言编译器以汇编代码的形式产生输出,汇编代码是机器代码的文本表示,给出程序中的每一条指令.然后GCC调用汇编器和连接器,从而根据汇编代码生成可执行的机器代码.

我们讨论的是IA32的中央处理器

2.1 Program Encodings 汇编

2.1.1 MACHINE-LEVEL CODE 机器级代码

简单的寄存器组

  • PC 程序计数器 用%eip标识 指示将要执行的下一条指令所在存储器中的地址.
  • xx寄存器 存储32位的值.可以存储地址(对应C语言中的指针)或整数数据. 用于记录某些重要的程序状态,保存临时数据,例如局部变量和程序的返回值.
  • xx寄存器 保存最近执行的算术或逻辑指令的状态信息, 用于实现控制或者数据流中的条件变化,例如if while等语句
  • 浮点寄存器

2.1.2 PROGRAM MEMORY

程序存储器:包含可执行的机器码,操作系统需要的一些信息,用来管理过程调用和返回的运行时栈,以及用户分配的存储器块(如malloc).程序存储器用虚拟地址寻址. 在任意给定的时刻,只认为有限的一部分虚拟地址是合法的.例如虽然IA32的32位地址可以寻址4GB的地址范围,但通常一个程序只会访问几兆的字节.操作系统负责管理虚拟地址空间,将虚拟地址翻译成实际处理器存储器中的物理地址.

2.2 Accessing Infomation

2.2.1 寄存器 REGISTER
  • 一个IA32的CPU包含一组8个存储32位值的寄存器.用于存储整数数据和指针. 名字都以%e开头
  • 前六个多数情况看成通用寄存器,
  • 最后两个寄存器 %ebp , %esp 保存着指向程序栈中重要位置的指针.例如: 栈指针%esp保存着栈顶元素的地址.

2.2.2 操作数指示符 OPERAND

指示出执行一个操作中要引用的源数据值,以及放置结果的目标位置. 三种类型:

  • 立即数寻址 (immediate) 即 常数值 |表示: ‘$’后跟一个标准C表示法表示的整数 |如 $Imm , $-577 , $0x1f .
  • 寄存器寻址 (register) | 如 %eax , %ax .
  • 存储器寻址 (memory) |寻址模式: 立即数偏移Imm,基址寄存器Eb,变址寄存器Ei,比例因子s.

2.2.3 数据传输指令 MOV
  1. 栈操作说明

    根据惯例,栈是倒着画的,因而栈顶在底部,IA32的栈向低地址方向增长,所以压栈是减小栈指针(寄存器%esp)的值,并将数据存放在存储器中,而出栈是从寄存器中读,并增加栈指针的值. #+imgs/stack.png wpid-stack.png

2.2.4 算术和逻辑操作 ARITHMETIC AND LOGICAL OPERATIONS
  1. 加载有效地址

    load effective address 指令 : leal . 从存储器读数据到寄存器.

  2. 一元操作与二元操作 Unary and Binary Operations
  3. 位移操作 Shift Operations
2.2.5 CONTROLL 流程控制
  1. Condition Codes
    1. condition code register : 条件代码寄存器
  2. Jump Instructions and Their Encodings 跳转指令及其编码
  3. Translating Conditional Branches 条件分支.
  4. Loops 循环
  5. Conditional Move Instructions 条件传送
  6. Switch *
2.2.6 PROCEDURES 过程

一个过程调用包括将数据(以过程参数和返回值的形式)和控制从代码的一部分传递到另一部分. 另外它还必须在进入时为过程的局部变量分配空间,并在退出时释放. 大多数机器,包括IA32,只提供转移控制到过程和从过程中转移出控制这种简单的指令. 数据传递,局部变量的分配和释放通过操纵程序栈来实现.

  1. Stack Frame Structure 栈帧结构

    机器用栈来传递过程参数,存储返回信息,保存寄存器用于以后恢复,以及本地存储. 为单个过程分配的那部分栈称为栈帧 . stack frame 栈帧的最顶端以两个指针界定:

    • 寄存器 %ebp 为帧指针;
    • 寄存器 %esp 为栈指针.

    stack2.png#+imgs/stack2.png wpid-stack2.png假设过程P(调用者)调用过程Q(被调用者),则Q的参数放在P的栈帧中. P的返回地址被压入栈中,形成P的栈帧的末尾,用于程序从Q中返回时继续执行的地方. Q的栈帧从保存的帧指针的值(%ebp)开始,后面是保存的其他寄存器的值.

    过程Q也用栈来保存其他不能存放在寄存器中的局部变量,原因如下:

    • 没有足够多的寄存器存放所有的局部变量;
    • 有些局部变量是数组或者结构,因此必须通过数据或结构引用来访问;
    • 要对一个局部地址使用地址操作符 ‘&’ , 所以要为它生成一个地址.

    另外Q会用栈帧存放调用它的过程的参数. 被调用的过程中,第一个参数放在相对于%ebp偏移量8的位置处,剩下的参数(假设数据类型需要的字节不超过4个)存储在后续的4字节块中.较大的参数(比如结构)需要栈上更大的区域.

    栈向低地址方向增长.

  2. Recursive Procedures 递归
2.2.7 ARRAY ALLOCATION AND ACCESS 数据的分配与访问

数组与指针的关系. * 讲的很详细

2.2.8 HETEROGENEOUS DATA STRUCTURES
  • structure 结构 编译器维护结构类型的信息,指示每个字段(field)的字节偏移.以这些偏移作为存储器引用指令中的位移,从而产生对结构元素的引用.
  • union 联合 以不同的字段来引用相同的存储器块.
  • Data Alignment 很有趣的一节,许多计算机系统对基本数据类型合法地址做出了一些限制,要求某种类型对象的地址必须是某个值K(2/4/8)的倍数. 这种对齐限制简化了形成处理器和存储器系统之间接口的硬件设计.例如:
struct S1{
    int i;
    char c;
    int j;
};
offset 0 4 5 8 12
value i c - j

以上:虽然char类型的c只占一个字节,但是因为windows设计了数据对齐限制,则5-8的内存地址空置了.

2.2.9 UNDERSTANDING POINTERS – PUTTING IT TOGETHER
  • 每个指针都有一个值,即某个指定类型对象的地址. 特殊的NULL(0)值表示该指针没有指向任何地方.
  • 指针用&运算符创建. leal指令是设计用来计算存储器引用的地址的,&运算符的机器代码实现经常用这条指令来计算表达式的值.
  • 操作符用于指针的间接引用. 其结果是一个值,类型与该指针的类型相关. 间接引用是通过存储器引用来实现的,要么是存储到一个指定的地址,要么是从指定的地址读取.
  • 指针与数组紧密练习.一个数组的名字可以像一个指针变量一样引用.(但不能修改)
  • 将指针从一种类型强制转换成另一种类型,只改变它的类型,而不改变它的值.
  • 指针也可以指向函数. 这提供了很强大的存储和向代码传递引用的功能. 函数指针的值是该函数机器代码表示中第一条指令的地址.
int fun (int x , int *p);
(int) (*fp) (int, int* );
fp = fun;
int y = 1;
int result = fp(3,&y);

2.2.10 USING THE GDB

值得一个课题研究.

2.2.11 3.12 存储器的越界引用和缓冲区溢出. OUT-OF-BOUNDS MEMORY REFERENCES AND BUFFER OVERFLOW
  1. 值得反复阅读. important

    详情参考书上的例子,在函数调用时分配char buf1; 而如果存储越界则会产生如下影响.

    char num effect
    0-7 none
    8-11 破坏%ebx存储的值
    12-15 破坏%ebp存储的值
    16-19 返回地址
    20+ callder中保存的状态
  2. 如何对抗溢出

2.3 x86-64 : Extending IA32 to 64 Bits .

全面总结 ,深度展望

2.4 c c++ java

早期编译C++与编译C 非常相似,实际上,C++的早期实现就只是简单的执行了从C++到C的源到源的转换,并对结果运行C编译器,产生目标代码.

C++的对象用结构来表示,类似C的struct. C++的方法是用指向实现方法的代码的指针来表示的.

相对而言,Java的实现方式完全不同,Java的目标代码是一种特殊的二进制表示,称为Java字节代码.这种代码可以看成虚拟机的机器级程序.

虚拟机并不是直接用硬件实现的,而是用软件解释器处理字节代码,模拟虚拟机的行为. 另外有一种称为及时编译 (Just-in-time compilation)的方法,动态地将字节代码序列翻译成机器指令.当代码要执行多次时(循环),这种方法执行起来更快.而且跨平台.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值