|
@ -96,7 +96,91 @@ |
|
|
|
|
|
|
|
|
Intel 和 IA-32 处理器都是采用“little endian(小端)”方式存储数据;这意味着 word 的字节序是从最低有效字节开始编号(译者注:关于“大端”和“小端”问题,请查看 [大端(Big-Endian)和小端(Little-Endian)](https://juejin.cn/post/6930889701507203085/#comment))。请看图1-1。 |
|
|
Intel 和 IA-32 处理器都是采用“little endian(小端)”方式存储数据;这意味着 word 的字节序是从最低有效字节开始编号(译者注:关于“大端”和“小端”问题,请查看 [大端(Big-Endian)和小端(Little-Endian)](https://juejin.cn/post/6930889701507203085/#comment))。请看图1-1。 |
|
|
|
|
|
|
|
|
|
|
|
### 1.3.2 保留位与软件兼容性 |
|
|
|
|
|
|
|
|
|
|
|
@翻译人:三分月色 |
|
|
|
|
|
|
|
|
|
|
|
在许多寄存器和内存布局描述中会有一些保留位。这些被标记为保留位的比特,是为了与未来的处理器兼容,尽管未来是未知的,软件仍将这些位视为对未来有重要影响。保留位的行为应该被认为是未定义(undefined)且不可预测的。 |
|
|
|
|
|
|
|
|
|
|
|
在处理保留位时,软件应遵循以下准则: |
|
|
|
|
|
|
|
|
|
|
|
* 当测试含保留位的寄存器的值时,不依赖保留位的状态。应在测试之前屏蔽掉保留位。 |
|
|
|
|
|
* 存储到内存或寄存器时,不依赖于保留位的状态。 |
|
|
|
|
|
* 不依赖保留位保持信息(retain information)的能力。 |
|
|
|
|
|
* 加载寄存器时,始终使用文档中指示的值加载保留位(如果有的话),或者使用先前从同一寄存器读取的值重新加载保留位。 |
|
|
|
|
|
|
|
|
|
|
|
<center>注意</center> |
|
|
|
|
|
|
|
|
|
|
|
避免任何软件依赖于 Inter 64和 IA-32 寄存器中的保留位状态。依赖寄存器的保留位,软件会依赖于处理器处理这些位的一种不确定的方式。依赖保留位的程序增加了与未来处理器不兼容的风险。 |
|
|
|
|
|
|
|
|
|
|
|
#### 1.3.2.1 指令操作符(Instruction Operands) |
|
|
|
|
|
|
|
|
|
|
|
(译者注:这里指令名称与操作数统称为 operands) |
|
|
|
|
|
|
|
|
|
|
|
当指令用符号表示时,会使用 IA-32 汇编语言的一个子集。在这个子集中,指令具有以下格式: |
|
|
|
|
|
|
|
|
|
|
|
标签:助记词(参数1),参数2, 参数3 |
|
|
|
|
|
|
|
|
|
|
|
其中: |
|
|
|
|
|
|
|
|
|
|
|
* 标签是一个唯一标识符,其后跟着一个冒号。 |
|
|
|
|
|
* 助记词是一类具有相同功能的指令操作码的保留名称(译者注:即指令名称)。 |
|
|
|
|
|
* 参数1、参数2、参数3 是可选的。根据操作码的不同,可能有 0~3 个参数。当他们出现的时候,采用数据项的字面意思或者标识符的形式。标识符要么是寄存器的保留名称,要么是假定赋值给程序中另一部分声明的数据项(可能在示例中没有显示)。 |
|
|
|
|
|
* 当算术或逻辑指令中有两个操作数时,右操作数是源,左操作数是目的。 |
|
|
|
|
|
|
|
|
|
|
|
例如: |
|
|
|
|
|
|
|
|
|
|
|
LOADREG: MOV EAX, SUBTOTAL |
|
|
|
|
|
|
|
|
|
|
|
在这个例子中,LOADREG 是标签,MOV 是操作码的助记标识符,EAX 是目标操作数,SUBTOTAL 是源操作数。有些汇编语言可能会将源和目标操作数放在相反的顺序。 |
|
|
|
|
|
|
|
|
|
|
|
### 1.3.3 16 进制与 2 进制数字 |
|
|
|
|
|
|
|
|
|
|
|
16 进制数字以一串 16 进制的数字(译者注:含字母)后跟字母 H 表示,(例如,0F82EH)。十六进制数字可以是0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F中的一个字符。 |
|
|
|
|
|
|
|
|
|
|
|
2 进制数字由 1 和 0 组成的字符串表示,有时后面跟着字符 B(例如,1010B)。只有在数字类型可能引起混淆的情况下才使用字符 B。 |
|
|
|
|
|
|
|
|
|
|
|
### 1.3.4 段寻址(Segmented Addressing) |
|
|
|
|
|
|
|
|
|
|
|
处理器使用字节寻址。这意味着内存是作为一个字节序列被组织和访问的。无论访问一个或多个字节,字节地址都用于定位单个字节或多个字节内存地址。可寻址的内存范围称为**地址空间**(address space)。 |
|
|
|
|
|
|
|
|
|
|
|
处理器也支持段寻址。这是一种寻址方式,程序可以有许多独立的地址空间,称为**段**(segments)。例如,一个程序可以将它的代码(指令)和堆栈保存在单独的段中。代码地址总是指向代码空间,堆栈地址总是指向堆栈空间。下面的表示法用于指定段内的字节地址: |
|
|
|
|
|
|
|
|
|
|
|
段寄存器:字节地址 |
|
|
|
|
|
|
|
|
|
|
|
例如,下面的段地址标识 DS 寄存器所指向的段中地址 FF79H 处的字节: |
|
|
|
|
|
|
|
|
|
|
|
DS:FF79H |
|
|
|
|
|
|
|
|
|
|
|
下面的段地址标识代码段中的指令地址。CS 寄存器指向代码段,EIP 寄存器包含指令的地址。 |
|
|
|
|
|
|
|
|
|
|
|
CS:EIP |
|
|
|
|
|
|
|
|
|
|
|
### 1.3.5 用于 CPUID、CR 和 MSR 值的新语法 |
|
|
|
|
|
|
|
|
|
|
|
通过使用 CPUID 指令、检查控制寄存器位和读取特定于模型的寄存器来获取特征标志、状态和系统信息。我们正在研究一种新的语法来表示这些信息。见图1 - 2。 |
|
|
|
|
|
|
|
|
|
|
|
### 1.3.6 异常 |
|
|
|
|
|
|
|
|
|
|
|
异常通常是指令出错时发生的事件。例如,尝试除以 0 会产生异常。然而,在其他条件下也会出现一些例外情况,例如断点(breakpoints)。某些类型的异常会提供错误码。错误码提供关于错误的附加信息。下面是用来显示异常和错误码的符号示例: |
|
|
|
|
|
|
|
|
|
|
|
\#PF(错误码) |
|
|
|
|
|
|
|
|
|
|
|
一个错误码定义了一种错误类型,上例是一个页面错误异常(page-fault exception)。在某些情况下,可能无法给到一个准确的错误码。在这种情况下,错误码为零,如下图所示为通用保护异常: |
|
|
|
|
|
|
|
|
|
|
|
\#GP(0) |
|
|
|
|
|
|
|
|
# 第二章 Intel 64 and IA-32 Architectures |
|
|
# 第二章 Intel 64 and IA-32 Architectures |
|
|
|
|
|
## 2.1 INTEL® 64 与 IA-32 架构的简要历史 |
|
|
|
|
|
|
|
|
|
|
|
以下章节提供了从 IA-32 到 Intel 64 架构的主要技术演进的摘要:从 Intel 8086 处理器开始到最新的 Intel®Core®2Duo,Core 2 Quad 和 Intel Xeon 处理器 5300 和 7300 系列。1978 年以前发布的处理器创建的对象代码仍然在 Inter 64 和 IA-32 架构系列中的最新处理器上运行着。 |
|
|
|
|
|
|
|
|
|
|
|
### 2.1.1 16 位处理器与段(1978) |
|
|
|
|
|
|
|
|
|
|
|
在 IA-32 体系结构家族之前,有 16 位处理器 8086 和 8088。8086 有 16 位寄存器和 16 位外部数据总线,20 位寻址提供 1-MByte 地址空间。8088 与 8086 相似,但它有一个 8 位的外部数据总线。 |
|
|
|
|
|
|
|
|
|
|
|
8086/8088 向 IA-32 架构引入了段(segmentation)。通过分段, 16 位段寄存器可以指向高达 64 KB 的内存段。同时使用四个段寄存器,8086/8088 处理器能够不在段之间切换的情况下寻址达 256 KB。使用段寄存器和额外的 16 位指针可以形成的 20 位地址提供 1 MB 的总寻址范围。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 第三章 Basic Execution Environment |
|
|
# 第三章 Basic Execution Environment |
|
|
|
|
|
|
|
|