Chinaunix首页 | 论坛 | 博客
  • 博客访问: 148508
  • 博文数量: 21
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 355
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-12 17:44
文章分类

全部博文(21)

文章存档

2011年(1)

2010年(5)

2009年(8)

2008年(7)

我的朋友

分类:

2010-01-08 15:55:18

前一阵子翻译了部分x86体系文档,这里放出来,希望对大家有用,有些不对的地方请拍砖。

2.1 内存组织和分段

80386系统的物理内存以8-bit为一个字节而组织。每个字节被分配一个唯一的地址,范围从02^32-1(4G).

然而80386程序独立于物理地址空间。这意味着程序可以在不知道物理内存大小以及指令和数据被存放的具体地址的情况下被写入。

应用程序员所看到的内存组织的模式是由系统软件设计者决定的。80386的架构给予了设计者为每个任务选择模式的自由。内存组织模式可以划分为下面的类型:

o. 04G组成的一段"平坦"地址空间

o. 最多由16383个分段的地址空间组成,每个地址空间最多可表示4G地址空间。(A segmented address space consisting of a collection of up to 16,383 linear address spaces of up to 4 gigabytes each.)

两种模式都可以提供内存保护,不同的任务可以采用不同的内存组织模式。设计者决定内存组织模式的标准以及系统程序员实现该模式的方法都被隐藏在编程部分中。

 

2.2.1 平坦模式

在平坦模式的内存组织中,应用程序员看到的是一段线性的地址空间,最大到4G。虽然物理内存可以达到4G,但是大多数情况下要远远小的多;处理器通过地址转换机制(将在第5章介绍)4G平坦地址空间映射到物理地址空间。应用程序员不需要知道映射的细节。

一个平坦地址空间的指针是一个32位的数值,范围从02^32-1。在这种地址空间下单独编译的模块必须由系统软件(如链接器,locators, binders, 加载器等)进行地址重定位。

 

2.2.2 分段模式

在分段模式下,应用程序员看到的地址空间(俗称逻辑地址空间)是一个非常大的范围,直到2^46字节(64T)。处理器通过地址转换机制(将在第5章介绍)64T的逻辑地址空间映射到物理地址空间(最大4G)上。应用程序员不需要知道映射的细节。

应用程序员看到的逻辑地址空间是一系列的一维子空间的集合(最大有16383个子空间),每个子空间有特定长度。这些子空间里的线性地址组成了一个段。一个段是连续的地址空间的集合,段大小可以从02^32字节(4G)

一个分段模式的完整指针由2部分组成(2-1)

1. 一个段选择器,16bit

2. 一个32bit段内偏移量

程序运行时,将一个段开始处的物理地址与段选择器关联。独立编译的模块在运行时通过改变他们的段基地址来进行重定向。段大小是可变的,因此一个段可以恰好是它所包含的模块大小。

 

2.2 数据类型

字节,字,双字是基本的数据类型(参见图2-2)1个字节是从任何一个逻辑地址开始的8个连续的位,从0标号到7,第0位被称为LSB(least significant bit)

字是从任意一个字节地址开始的连续2字节。包含16位,包含第0位的字节称为低字节,包含第15位的称为高字节。

每个字的字节都有自己的地址,这是一个比字要小的地址。低字节地址包含字的8LSB,高字节地址包含字的8MSB(most significant bits)

双字是从任意一个字节地址开始的连续2字。包含32位。包含第0位的字称为低字,包含第31位的称为高字。

每个双字的字节都有自己的地址,这是双字中最小的地址。低字节地址包含双字的8LSB,高字节地址包含双字的8MSB(most significant bits)。参见图2-3

请注意,字不需要开始在偶数地址空间,而双字也不需要开始在4的倍数的地址空间上。这使数据结构的灵活性以及内存使用的效率都达到了最大。当使用32位总线时,处理器和内存之间要传递双字的数据,地址空间必须开始在4的倍数(内存特性决定了CPU只可以存取4倍数的地址空间),对于这些不在边界上的字或者双字(misaligned data),处理器会转换这些请求来迎合内存的接口。这些misaligned data的传输会导致性能的降低,因为它要求额外的存储周期。为了最大的性能要求,数据结构(包括栈)应该以这样一种方式设计:无论何时,尽可能的让字对其在偶地址,让双字对其在4倍地址空间上。由于取指令是在CPU内部进行处理,所以指令不要求对其在字或双字边界上。

处理器还支持额外类型的操作数:

Integer:

      有符号二进制数字的值,32bit16bit或者8bit。最高位为符号位

Ordinal

      无符号二进制数字的值,32bit16bit或者8bit

Near Pointer:

      32bit逻辑地址。1个近指针是一个段内偏移量,可以在平坦或分段的内存模式中使用

Far Pointer:

      48bit的逻辑地址,分为2个部分:16bit的段选择器部分以及32bit的偏移量。仅当系统设计者选择分段内存模式时,应用程序员才会使用远指针。

String:

      字节,字或双字的连续序列。一个串可以包含从0字节直到2^32-1字节

Bit field:

      Bits的连续序列。一个位域可以从任意字节的任意位开始直到32bits

Bit string:

      Bits的连续序列。一个位域可以从任意字节的任意位开始直到2^32-1bits

BCD:

      一个字节用来表示一个0-910进制数字。未压缩的十进制数字被存储在无符号的字节中。一个字节存放十进制数字。数字被放在低4位中,乘法和除法时高4位必须是0,加法或减法时,可以为任意值

Packed BCD:

      一个字节用来表示两个0-910进制数字。半字节存放一个数字,高位是最高权重(即高4位存放十进制数的高位)。压缩的BCD范围是0-99

 

2-4总结了80386支持的数据类型

 

2.3 寄存器

80386包括16个可能让应用程序员感兴趣的寄存器,参见图2-5,可以分为以下三类:

1. 通用寄存器:832位的通用寄存器,主要用来存放算数及逻辑指令的操作数

2. 段寄存器:这6个特殊的寄存器,允许系统软件设计者选择平坦内存模式或者分段内存模式。这些寄存器决定了任意给定时刻,内存正在寻址的段。

3. 状态和指令寄存器:这些特殊的寄存器记录或改变处理当前状态

 

2.3.1 通用寄存器

80386包含832位的通用寄存器:EAX, EBX, ECX, EDX, EBP, ESP, ESIEDI。主要用来存放算数及逻辑指令的操作数,也可以用来进行地址计算(除了ESP不可以用作索引操作数)

如图2-5所示,每个寄存器的低字还可以被单独作为一个单元而拥有独立的名字,这加强了处理16bit数据的灵活性,同时也兼容808680286处理器。字寄存器被命名为AX,BX,CX,DX,BP,SP,SIDI

2-5还能看出,每个AX,BX,CX,DX寄存器的字节还可以被单独作为一个单元而拥有独立的名字,这对加强了处理字符和8bit数据的灵活性。这些字节寄存器被命名为AH,BH,CHDH(高字节);AL,BL,CLDL(低字节)

 

有些功能只限于特定的寄存器完成,如double-precision multiply and divide, I/O, string instructions, translate, loop, variable shift and rotate, and stack operations.

 

2.3.2 段寄存器

80386段寄存器给了系统软件设计者选择不同内存模式极大的灵活性。设计者可以选择一个应用程序员不必修改段寄存器的内存模式。

一个完整的程序由多个不同的模块组成,每个模块又包含指令和数据,然而实际运行中,仅仅只有一小部分模块在被使用。80386系统利用这一个特性,实现了一种机制:支持直接访问当前模块的数据和指令地址,按需访问其他模块的段地址。(The 80386 architecture takes advantage of this by providing mechanisms to support direct access to the instructions and data of the current module's environment, with access to additional segments on demand)

6个段寄存器是CS,DS,SS,ES,FSGS(如图2-6)

包含当前执行指令序列的段称为代码段。通过CS寄存器指定。80386从代码段取得的指令中的指针都是段内偏移量(The 80386 fetches all instructions from this code segment, using as an offset the contents of the instruction pointer.)CS寄存器会被CALL,JMP等指令,中断或异常改变。

所有的栈操作使用SS寄存器来定位栈地址,与CS寄存器不同,程序员可以动态的改变SS的值。

DS, ES, FS, GS指定了运行期间的四个数据段。分为独立的四个数据单元可以帮助程序更高效地获取不同类型的数据结构,例如:一个数据段寄存器可以指向当前模块的数据结构,一个指向高层模块导出的数据,一个指向动态创建的数据结构,另一个指向共享数据。数据段内的操作数的偏移量被直接在指令中编址或通过寄存器获取。

一个程序可能需要多余4个数据段,为了访问到这些段DS, ES, FS, GS寄存器的值可以被更改通过编程来实现。这只要求程序执行加载合适段寄存器的指令优先于执行获取数据的指令。

处理器将段寄存器所选择的段与一个基地址相关联。在段内寻址一个元素,32bit的偏移量被加到段的基地址上。一但一个段被选择(加载段选择器到段寄存器),一个数据操作的指令仅仅需要指定偏移量。简单的规则定义了当只有偏移量时,使用哪个段寄存器组成地址。

 

2.3.3 栈实现

stack segment (SS)寄存器: 栈实现在内存。一个栈最大可以是4G(一个段的最大值) SS自动的被处理器设置,指定当前栈段。

stack pointer (ESP) register:指向当前栈段的栈顶指针(TOS)。它被PUSHPOP指令,子过程调用和返回,中断操作等引用。当一个元素入栈(2-7)处理器减少ESP,在新的TOS上写入元素值。当一个元素出栈,处理器增加ESP,在新的TOS上写入元素值。换句话说,栈向低地址处生长。

stack-frame base pointer (EBP) register:在栈内访问数据结构,变量以及动态分配空间的话,EBP是最好的寄存器。EBP通常用来存取那些相对栈内某个固定位置的元素而不是相对TOS的位置的元素。它表示了为当前过程建立的栈框架的基地址。当EBP作为偏移量计算的基地址时,偏移量在当前的栈段被自动的计算。由于SS不能显式设置,指令在这种模式下非常高效。EBP也可以用于索引其他段寄存器指定的段内地址。

 

2.3.4 标志寄存器

名为EFLAGS32bit寄存器(2-8)。它控制特殊操作以及显示80386处理器状态。

低位的16字节命名为FLAGS,可以作为一个独立的寄存器。当执行808680286代码的时候非常有用,因为这部分内容与808680286FLAGS寄存器相同。

这些标志可以分为三组:状态标志,控制标志,以及系统标志。系统标志在第二部分说明。

2.3.4.1 状态标志

状态标志允许一条指令的结果影响后续的指令。算术指令使用OF, SF, ZF, AF, PF, CFSCAS (Scan String), CMPS (Compare String),以及LOOP指令使用ZF来通知操作已经完成。算术指令之前有设置,清空,补码CF标志。

 

2.3.4.2 控制标志

控制标志控制串指令。DF(Direction Flag, bit 10)。设置DF导致串指令自减;这就是从高地址向低地址处理串。清空DF导致串指令自增,从低地址向高地址处理串

 

2.3.4 指令指针

instruction pointer register (EIP)包含了下一条指令的相对于当前代码段的偏移量。指令指针对程序员不可见,它被控制传输指令,中断和例外隐式设定(2-9)。低16位命名为IP可以被当作单独的寄存器使用,当执行808680286代码的时候非常有用。

 

 

 

2.4 指令格式

80386指令包括要执行的操作,操作数类型以及这些操作数的位置。如果操作数在内存中,指令必须显式或隐式地选择包含此操作数的可寻址段。

80386指令由多种元素组成,并有多种格式。具体的格式请参见附录。下面讨论指令包含的元素。在这些元素中,仅有操作码总是必须的,特定操作以及操作数的位置和种类决定了其它元素是可选的。指令的元素按下面的顺序出现:

o. 前缀 在指令前1个或多个字节,修改指令的操作。有下面几种类型前缀可以被应用程序员使用:

   1Segment override – 显式地指定指令使用的段寄存器,覆盖了指令默认选择的段寄存器

   2Address size – 32位和16位两种

   3Operand size – 32位和16位两种

   4Repeat – 用在串指令中,使指令作用于串中的每个元素

o. 操作码 指明了指令执行的操作。某些操作有不同的操作码,每个指明了操作的不同变种。

o. 寄存器指示符 一条指令可以指定1个或2个寄存器操作数。寄存器指示符可以与操作码或地址模式指示符出现在同一字节中。

o. 地址模式指示符 当它存在时,指示操作数是内存操作数还是寄存器操作数。如果在内存中,指示是否使用displacementbase registerindex register,和scale

o. SIB(scale, index, base)字节 当地址模式操作符指示一个index寄存器被用于计算操作数地址时,指令会包括一个SIB字节来编码base寄存器,index寄存器以及scale因子。

o. Displacement -- 当地址模式操作符指示displacement被用于计算操作数地址时,displacement被编码进指令。Displacement是一个32位,16位或8位的有符号的整数。当displacement非常小的时候,通常使用8位格式。考虑到符号,处理器会扩充一个8位到16位或32位。

o. 立即操作数 当它存在时,直接表示操作数的值。立即操作数可以是8位,16位或32位宽。

阅读(1621) | 评论(0) | 转发(0) |
0

上一篇:MCU and Soc

下一篇:转载-时间

给主人留下些什么吧!~~