IA-32架构CPU运行环境

本文涉及的产品
公网NAT网关,每月750个小时 15CU
简介: IA-32架构CPU运行环境

IA-32架构 CPU基本的执行环境



操作方式

IA-32体系结构支持三种基本操作模式:保护模式、真实地址模式和系统管理模式。操作模式确定可访问哪些说明和体系结构功能:


保护模式


此模式是处理器的本机状态。受保护模式的功能包括能够在受保护的多任务环境中直接执行"真实地址模式"8086软件。这个功能被称为虚拟-8086模式,尽管它实际上并不是一种处理器模式。虚拟8086模式实际上是一个可受保护的模式属性,可以为任何任务启用。


真实地址模式


此模式通过扩展功能实现了Intel8086处理器的编程环境(例如能够切换到受保护模式或系统管理模式)。通电或重置后,处理器处于实际地址模式。


系统管理模式** (SMM)**


此模式为操作系统或执行人员提供透明的机制来实现平台的功能,如电源管理和系统安全。当外部SMM中断针(SMI#)被激活或从高级可编程中断控制器(APIC)接收到SMI时,处理器进入SMM。


在SMM中,处理器切换到单独的地址空间,同时保存当前运行的程序或任务的基本上下文。然后,SMM特定的代码可以透明地执行。从SMM返回后,处理器将被放回到系统管理中断之前的状态。SMM采用了Intel386™SL和Intel486™SL处理器,并成为奔腾处理器系列的标准IA-32功能。


Intel®64架构

Intel64架构增加了IA-32e模式。IA-32e模式有两个子模式。以下包括:


兼容性模式(** IA-32e **模式的子模式)


兼容性模式允许大多数遗留的16位和32位应用程序在64位操作系统下运行,而无需重新编译。为了简洁起见,兼容性子模式在IA-32架构中被称为兼容性模式。兼容模式的执行环境与后面描述的32位系统模式相同。兼容性模式还支持在64位和受保护模式下支持的所有特权级别。在虚拟8086模式下运行或使用硬件任务管理的旧版应用程序在此模式下无法工作。


操作系统(OS)基于代码段启用了兼容性模式。这意味着单个64位操作系统可以支持以64位模式运行的64位应用程序,并支持以兼容模式运行的传统32位应用程序(不为64位重新编译)。


兼容性模式类似于32位保护模式。应用程序只能访问线性地址空间的前4G字节。兼容性模式使用16位和32位的地址和操作数大小。与受保护模式一样,此模式允许应用程序使用PAE(物理地址扩展)访问超过4G字节的物理内存。


64** 位模式( IA-32e 模式的子模式)**


该模式使64位操作系统能够运行写入以访问64位线性地址空间的应用程序。为了简洁起见,64-位子模式在IA-32架构中被称为64位模式。


64位模式将通用寄存器和SIMD扩展寄存器的数量从8个扩展到16个。通用寄存器被扩大到64位。该模式还引入了一个新的操作码前缀(REX)来访问寄存器扩展。详细说明详见后面章节。


操作系统基于代码段启用64位模式。它的默认地址大小是64位,它默认的操作数大小是32位。可以使用REX操作码前缀和操作数大小覆盖前缀逐个操作指令地覆盖默认操作数大小。


REX前缀允许在64位模式下操作时指定64位操作数。通过使用这种机制,许多现有的指令已经被提升,以允许使用64位寄存器和64位地址。


基本执行环境的概述

在IA-32处理器上运行的任何程序或任务都有一组执行指令和存储代码、数据和状态信息的资源。这些资源(在以下段落中简要说明,如图3-1所示)构成了IA-32处理器的基本执行环境。


Intel64处理器支持IA-32处理器的基本执行环境,以及在IA-32e模式下的类似环境,可以执行64位程序(64位子模式)和32位程序(兼容子模式)。


基本的执行环境由应用程序和在处理器上运行的操作系统或执行程序联合使用。


地址空间


在IA-32处理器上运行的任何任务或程序都可以解决最多高达4G字节的线性地址空间和高达64G字节的物理地址空间。有关寻址大于4G字节的地址空间的详细信息,请参见第"受保护模式下的扩展物理寻址"。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eup0OdJ9-1622795531757)(RackMultipart20210604-4-42zeu4_html_9464027175030086.png)]

20210604163714887.png

图3-1 IA-32非64位模式的基本执行环境


基本程序执行寄存器


八个通用寄存器、六个段寄存器、EFLAGS寄存器和EIP(指令指针)寄存器包括一个基本执行环境,在其中执行一组通用指令。这些指令对字节、字和双字整数执行基本的整数运算、处理程序流控制、操作位和字节字符串以及地址内存。有关这些寄存器的详细信息,请参见"基本程序执行寄存器"。


x87FPU** 寄存器**


8个x87FPU数据寄存器、x87FPU控制寄存器、x87FPU指令指针寄存器、x87FPU指令指针寄存器、x87FPU操作数(数据)指针寄存器、x87FPU标记寄存器和x87FPU操作码寄存器提供了操作单精度、双精度和双扩展精度浮点值、字整数、双字整数、四字整数和二进制编码十进制(BCD)值的执行环境。有关这些寄存器的详细信息,请参见"x87FPU执行环境"。


MMX** 寄存器**


八个MMX寄存器支持对64位打包字节、字符和双字整数执行单指令、多数据(SIMD)操作。有关这些寄存器的详细信息,请参见"MMX技术编程环境"。


XMM** 寄存器**


8个XMM数据寄存器和MXCSR寄存器支持对128位压缩单精度和双精度浮点值以及128位打包字节、字、双字和四字整数执行SIMD操作。有关这些寄存器的详细信息,请参见"SSE编程环境"。


YMM** 寄存器**


YMM数据寄存器支持对256位打包的单精度和双精度浮点值以及256位打包的字节、字、双字和四字整数执行256位SIMD操作。


Bounds** 寄存器**


每个Bounds寄存器都存储与指向内存缓冲区的指针关联的下限和上限(每个64位)。它们支持执行IntelMPX指令。


BNDCFGU and BNDSTATUS


BNDCFGU在边界检查时配置用户模式MPX操作。BNDSTATUS提供了有关由MPX操作引起的#BR的附加信息。


堆栈


为了支持过程或子程序调用以及过程或子程序之间的参数传递,执行环境中包含了堆栈和堆栈管理资源。堆栈(图3-1中没有所示)位于内存中。有关堆栈结构的更多信息,请参见第"堆栈"。


除了在基本执行环境中提供的资源外,IA-32架构还作为其系统级架构的一部分提供了以下资源。它们为操作系统和系统开发软件提供了广泛的支持。除I/O端口外,系统资源将在Intel®64和IA-32架构软件开发人员手册第3A和3B卷中详细描述。


  1. 输入输出端口
  2. IA-32体系结构支持对输入/输出(I/O)端口的数据传输。请参见本卷中的第19章"输入/输出"。

  3. 控制寄存器
  4. 五个控制寄存器(CR0到CR4)确定了处理器的操作模式和当前正在执行的任务的特征。

  5. 内存管理寄存器
  6. GDTR、IDTR、任务寄存器和LDTR指定在受保护模式内存管理中使用的数据结构的位置。

  7. 调试寄存器
  8. 调试寄存器(DR0到DR7)控制,并允许监视处理器的调试操作。

  9. 内存类型范围寄存器(MTRR)
  10. MTRR用于将内存类型分配给内存区域。

  11. 特定于型号的寄存器(MSR)
  12. 该处理器提供了各种特定于模型的寄存器,用于控制和报告处理器的性能。几乎所有的MSR都处理与系统相关的功能,并且应用程序无法访问。此规则的一个例外是时间戳计数器。

  13. 机器检查寄存器
  14. 机器检查寄存器包括一组控制、状态和错误报告MSR,用于对硬件(机器)错误进行检测和报告这些MSR。

  15. 性能监视计数器
  16. 性能监视计数器允许监视处理器的性能事件。

64位模式的执行环境

64位模式的执行环境类似于后面所述的执行环境。以下几段描述了适用的差异。


地址空间


在IA-32处理器上以64位模式运行的任务或程序可以解决最多264字节的线性地址空间(根据第3.3.7.1节所述的规范寻址要求)和最多252字节的物理地址空间。软件可以查询CPUID的处理器支持的物理地址大小。


基本程序执行寄存器


可用的通用寄存器(GPR)的数量为16个。GPR有64位宽,它们支持对字节、字、双字和四字整数的运算。访问字节寄存器要统一达到最低的8位。指令指针寄存器变为64位。EFLAGS寄存器被扩展到64位宽,并被称为RFLAGS寄存器。保留了上部32位的RFLAGS。较低的32位的RFLAGS与EFLAGS相同。详见图3-2。


XMM** 寄存器**


对于SIMD操作,有16个XMM数据寄存器。有关这些寄存器的详细信息,请参见第10.2节"SSE编程环境"。


YMM** 寄存器**


对于SIMD操作,有16个YMM数据寄存器。有关这些寄存器的详细信息,请参见第14章"使用AVX、FMA和AVX2编程"。


BND** 寄存器**


状态和状态-请参见第13章"使用XSAVE功能集管理状态"和第17章"Intel®MPX"。


堆栈


堆栈指针的大小为64位。堆栈大小不由SS描述符中的一点来控制(因为它在非64位模式下),也不能用指令前缀覆盖指针的大小。


控制寄存器


控制寄存器将扩展到64位。已添加了一个新的控制寄存器(任务优先级寄存器:CR8或TPR)。请参见本卷中的第2章"Intel®64和IA-32架构"。


调试寄存器


调试寄存器将扩展到64位。请参见Intel®64和IA-32架构软件开发人员手册第3A卷中的第17章"调试、分支配置文件、TSC和服务质量"。


描述符表寄存器


全局描述符表寄存器(GDTR)和中断描述符表寄存器(IDTR)扩展到10个字节,以便它们可以保持一个完整的64位基地址。本地描述符表寄存器(LDTR)和任务寄存器(TR)也会扩展到保持一个完整的64位基地址。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HaCZOAb0-1622795531759)(RackMultipart20210604-4-42zeu4_html_75ec6c3da1821f20.png)]

20210604163752758.png

图3-2 64位模式的执行环境


存储器组织

处理器在其总线上地址的内存称为物理内存。物理内存被组织为一个8位字节的序列。每个字节都被分配了一个唯一的地址,称为物理地址。如果处理器不支持Intel64体系结构,则物理地址空间的范围从0到最大236−1 (64 G字节)不等。Intel64体系结构引入了物理和线性地址空间的变化;这些在第3.3.3节第3.3.4节和第3.3.7节中描述。


事实上,任何设计使用IA-32或Intel64处理器的操作系统或执行都将使用处理器的内存管理设施来访问内存。这些设施提供了分割和分页等功能,这允许内存被有效和可靠地管理。在Intel®64和IA-32体系结构软件开发人员手册第3A卷的第3章"保护模式内存管理"中详细描述了内存管理。以下段落描述了在使用内存管理时对内存进行寻址的基本方法。


IA-32内存模型

当使用处理器的内存管理设施时,程序不会直接处理物理内存。相反,它们使用三种内存模型之一的方式访问内存:平面模式、分段模式或真实地址模式:


平面内存模型


程序将内存显示为单个连续的地址空间(图3-3)。这个空间被称为线性地址空间。代码、数据和堆栈都包含在此地址空间中。线性地址空间可进行字节寻址,地址从0到232-1连续运行(如果不是在64位模式下)。线性地址空间中的任何字节的地址都称为线性地址。


分段内存模型


内存向程序中显示为一组称为段的独立地址空间。代码、数据和堆栈通常包含在单独的数据段中。要处理段中的一个字节,程序会发出一个逻辑地址。这由一个段选择器和一个偏移量组成(逻辑地址通常被称为远点指针)。段选择器标识要访问的段,而偏移量标识段的地址空间中的一个字节。在IA-32处理器上运行的程序最多可处理16,383个不同大小和类型的段,每个段可达232个字节。


在内部,为系统定义的所有段都被映射到处理器的线性地址空间中。为了访问存储器位置,处理器因此将每个逻辑地址转换为线性地址。此转换对应用程序是透明的。


使用分段内存的主要原因是为了提高程序和系统的可靠性。例如,将程序的堆栈放在单独的段中可以防止堆栈增长到代码或数据空间中,并分别覆盖指令或数据。


真实地址模式内存模型


这是Intel8086处理器的内存模型。支持提供与在Intel8086处理器上运行的现有程序的兼容性。实际地址模式使用分段内存的特定实现,其中程序和操作系统/执行程序的线性地址空间由每个段最多64K字节的段数组组成。实际地址模式下线性地址空间的最大大小为220字节。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MqNIwZzs-1622795531760)(RackMultipart20210604-4-42zeu4_html_7ab3cdb1a6a96ddb.png)]


20210604163829714.png

图3-3 三种内存管理模型


分页和虚拟内存

对于平面存储模型或分段内存模型,线性地址空间可以直接或通过分页方式映射到处理器的物理地址空间中。当使用直接映射(禁用分页)时,每个线性地址都与物理地址具有一对一的对应关系。线性地址在处理器的地址线上发送,而无需转换。


当使用IA-32架构的分页机制(启用分页)时,线性地址空间被分成映射到虚拟内存的页面。然后,虚拟内存的页面根据需要被映射到物理内存中。当操作系统或执行人员使用分页时,分页机制对应用程序是透明的。应用程序所看到的只是线性地址空间。


此外,IA-32体系结构的分页机制包括支持的扩展:


物理地址扩展(PAE),地址大于4G字节的物理地址空间。


页面大小扩展(PSE),将线性地址映射到4兆字节页面中的物理地址。


64位模式下的内存组织结构

Intel64体系结构支持大于64G字节的物理地址空间;IA-32处理器的实际物理地址大小是特定于实现的。在64位模式下,对64位线性地址空间有体系结构支持。但是,支持Intel64架构的处理器可能会实现小于64位(请参见第3.3.7.1节)。线性地址空间通过PAE寻呼机制映射到处理器的物理地址空间中。


操作模式与内存模式

当为IA-32或Intel64处理器编写代码时,程序员需要知道在执行代码和所使用的内存模型时,处理器将处于的操作模式。工作模式与内存模式之间的关系如下:


保护模式


在保护模式下,处理器可以使用前面描述的任何内存模型。(实际寻址模式中内存模式通常仅在处理器处于虚拟8086模式时使用。)所使用的内存模型取决于操作系统或执行器的设计。当实现多任务处理时,单个任务可以使用不同的内存模型。


真实地址模式


当处于真实地址模式时,处理器仅支持真实地址模式内存模型。


系统管理模式


在SMM(系统管理模式)中,处理器切换到一个单独的地址空间,称为系统管理RAM(SMRAM)。用于在此地址空间中地址字节的内存模型类似于实际地址模式模型。有关SMM中使用的内存模型的更多信息,请参见Intel®64和IA-32《架构软件开发人员手册》第34章中的"系统管理模式"。


兼容性模式


需要在兼容模式下运行的软件应观察到与目标要以32位保护模式运行的软件相同的内存模型。段的效果与它在32位保护模式语义中的效果相同。


64** 位模式**


段通常被禁用(但不是完全),从而创建一个平坦的64位线性地址空间。具体地说,处理器在64位模式下将CS、DS、ES和SS的段基视为零(这使得线性地址等于有效地址)。在64位模式下的段和真实地址模式是无效的。


32位和16位的地址和操作员尺寸

在受保护模式下的IA-32处理器可以被配置为32位或16位的地址和操作数大小。对于32位地址和操作数大小,最大线性地址或段偏移量为FFFFFFFFH(232-1);操作数大小通常为8位或32位。对于16位地址和操作数大小,最大线性地址或段偏移量为FFFFH(216-1);操作数大小通常为8位或16位。


当使用32位寻址时,逻辑地址(或远指针)由16位段寄存器和32位偏移器组成;当使用16位寻址时,地址由16位段选择器和16位偏移器组成。


指令前缀允许从程序中临时覆盖默认地址或操作数大小。


在受保护模式下操作时,当前执行的代码段的段描述符定义默认地址和操作数大小。段描述符是一种对应用程序代码通常不可见的系统数据结构。汇编程序指令允许为程序选择默认的寻址和操作数大小。汇编程序和其他工具随后为代码段适当地设置段描述符。


在实际地址模式下操作时,默认寻址和操作数大小为16位。一个地址大小的覆盖可以使用在实际地址模式来启用32位寻址。但是,允许的最大32位线性地址仍然是000FFFFFH(220-1)。


在受保护模式下的扩展物理寻址

从P6系列处理器开始,IA-32体系结构支持最多64G字节(236字节)的物理内存的寻址。程序或任务无法直接指向物理内存地址空间中的位置。相反,它通过虚拟内存管理机制映射了单个高达4G字节的线性地址空间到64G字节的物理地址空间。使用这种机制,操作系统可以使程序在64G字节的物理地址空间内切换4G字节的线性地址空间。


扩展物理寻址的使用要求处理器在保护模式下操作,操作系统提供虚拟内存管理系统。请参见Intel®64和IA-32架构软件开发人员手册第3A卷第3章"保护模式内存管理"中的"使用PAE寻呼机制的36位物理寻址"。


在64位模式下的地址计算

在大多数情况下,64位模式对代码、数据和堆栈使用平面地址空间。在64位模式下(如果没有地址大小覆盖),有效地址计算的大小为64位。有效地址计算使用64位基地址和索引寄存器,并通过符号扩展位移到64位。


在64位模式的平面地址空间中,线性地址等于有效地址,因为基本地址为零。如果FS或GS段使用了非零基,则此规则不成立。在64位模式下,在添加完整的64位段基之前,添加有效地址组件并截断有效地址(例如参见指令LEA)。无论64位模式下的寻址模式如何,基线都不会被截断。


指令指针扩展到64位以支持64位代码偏移。这个64位的指令指针被称为RIP。表3-1显示了RIP、EIP和IP之间的关系。


表3-1 指令指针大小


|


位数:63:32 位数:31:16 位数15:0

16位指令指针 不改变 IP

32位指令指针 填充0 EIP

64位指令指针 RIP

一般来说,64位模式下的偏移数和立即数不会扩展到64位。它们仍然被限制在32位以内,并在有效地址计算过程中进行符号扩展。然而,在64位模式下是支持64位位移和直接形式的MOV指令。


所有16位和32位地址计算都在IA-32e模式下进行零扩展,形成64位地址。地址计算首先被截断为当前模式的有效地址大小(64位模式或兼容模式)的有效地址大小,并被任何地址大小的前缀覆盖。然后,结果被零扩展到完整的64位地址宽度。因此,在兼容模式下运行的16位和32位应用程序只能访问64位模式有效地址的低4G字节地址。同样,在64位模式下生成的32位地址只能访问64位模式有效地址的低4G字节。


规范的寻址

在64位模式下,如果地址位63到微体系结构的最重要的实现位被设置都为零或其余都为零,则该地址被认为是规范形式的。


Intel64体系结构定义了一个64位的线性地址。实现可以支持的数量很少。带有Intel64架构的IA-32处理器的首次实现支持一个48位线性地址。这意味着规范地址必须将位63到48设置为零或1(取决于位47是零还是1)。


虽然实际可能不使用线性地址的所有64位,但它们应该通过最重要符号检查方式来检查位63,以查看该地址是否为规范形式。如果线性内存引用不是规范形式,则实际应生成异常。在大多数情况下,会生成一般保护异常(#GP)。但是,在显式或隐含的堆栈引用的情况下,会生成一个堆栈故障(#SS)。


默认情况下,具有隐含堆栈引用的指令使用SS段寄存器。这些指令包括PUSH/POP相关的指令和使用RSP/RBP作为基本寄存器的指令。在这些情况下,标准故障为#SS。


如果指令使用基本寄存器RSP/RBP并使用段覆盖前缀来指定非SS段,则规范故障将生成一个#GP(而不是#SS)。在64位模式下,仅适用FS和GS段覆盖。将忽略其他段覆盖前缀(CS、DS、ES和SS)。请注意,这也意味着,应用于"非堆栈"寄存器引用的SS段覆盖将被忽略。这样的序列仍然会为规范故障(生成#GP,而不是#SS)。


基本的程序执行寄存器

IA-32体系结构提供了16个基本程序执行寄存器(见图3-4)。这些寄存器可以分组如下:


  1. 通用的寄存器: 这八个寄存器可用于存储操作数和指针。
  2. 段寄存器: 这些寄存器最多可容纳6个数据段选择器。
  3. EFLAGS** (程序状态和控制)寄存器:**EFLAGS寄存器报告正在执行程序的状态,并允许处理器的有限(应用程序级别)控制。
  4. EIP** (指令指针)寄存器:**EIP寄存器包含一个指向要执行的下一个指令的32位指针。

通用寄存器

32位通用寄存器EAX、EBX、ECX、EDX、ESI、EDI、EBP和ESP可保存以下各项:


  • 逻辑和算术运算的运算数
  • 地址计算的运算数
  • 内存指针

尽管所有这些寄存器都可用于操作数、结果和指针的一般存储,但在引用ESP寄存器时应谨慎使用。ESP寄存器保存堆栈指针,一般情况下不应该用于其他用途。


许多指令分配特定的寄存器来保存操作数。例如,字符串指令使用ECX、ESI和EDI寄存器的内容作为操作数。当使用分段内存模型时,一些指令假设某些寄存器中的指针相对于特定的段。例如,一些指令假定EBX寄存器中的指针指向DS段中的内存位置。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-em0ew1UG-1622795531761)(RackMultipart20210604-4-42zeu4_html_2b320bbf1df1ea4a.png)]

20210604163850990.png


图3-4 通用系统和应用程序编程寄存器


本卷第 5 章"指令集摘要"介绍了通用寄存器的特殊用途。另请参见: Intel®64 和 IA-32 架构软件开发人员手册的第 3 章、第 4 章和第 5 章,第 2A 、 2B 和 2C 卷。


以下是对通用寄存器的特殊用途的总结:


EAX:操作数和结果数据的累积器


EBX:指向DS段中的数据的指针


EDX:I/O指针


ESI:指向DS寄存器所指向的段中数据的指针;用于字符串操作的源指针


EDI:指向ES寄存器指向的段中的数据(或目标)的指针;用于字符串操作的目标指针


ESP:堆栈指针(在SS段中)


EBP:指向堆栈上数据的指针(在SS段中)


如图3-5所示,通用寄存器的下16位直接映射到8086和Intel286处理器中的寄存器集,并且可以使用名称AX、BX、CX、DX、BP、SI、DI和SP来引用。EAX、EBX、ECX和EDX寄存器的下两个字节都可以通过名称AH、BH、CH和DH(高字节)和AL、BL、CL和DL(低字节)来引用。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xq5uKcGL-1622795531762)(RackMultipart20210604-4-42zeu4_html_568ca3693d6c7d34.png)]

20210604163915113.png


图3-5 备用通用寄存器名称


64位模式下的通用寄存器

在64位模式下,有16个通用寄存器,默认操作数大小为32位。然而,通用寄存器能够使用32位或64位操作数。如果指定了32位操作数大小:EAX、EBX、ECX、EDX、EDI、ESI、EBP、ESP、R8D-R15D可用。如果指定了64位操作数大小:RAX、RBX、RCX、RDX、RDI、RSI、RBP、RSP、R8-R15可用。R8D-R15D/R8-R15代表8个新的通用寄存器。所有这些寄存器都可以在字节、字符、d字符和qword级别上访问。REX前缀用于生成64位操作数大小或指定寄存器R8-R15。


R8-R15和XMM8-XMM15的值仅在从64位模式到兼容模式然后回到64位模式的过渡的过程中保留。然而,在从64位模式到兼容模式过渡到传统模式,然后通过兼容模式返回到64位模式后,R8-R15和XMM8-XMM15的值未定义。


表3-2 可寻址的通用用途寄存器


寄存器类型 没有前缀(REX) 具有前缀(REX)

字节寄存器(byte) AL, BL, CL, DL, AH, BH, CH, DH AL, BL, CL, DL, DIL, SIL, BPL, SPL, R8B - R15B

字寄存器(Word) AX, BX, CX, DX, DI, SI, BP, SP AX, BX, CX, DX, DI, SI, BP, SP, R8W - R15W

双字寄存器(doubleword) EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP, R8D - R15D

4字寄存器(Quadword) 无 RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP, R8 - R15

在64位模式下,访问字节寄存器存在限制。指令不能同时引用旧的高字节(例如:AH、BH、CH、DH)和一个新字节寄存器(例如:RAX寄存器的低字节)。但是,指令可以同时引用旧的低字节(例如:AL、BL、CL或DL)和新字节寄存器(例如:R8寄存器的低字节,或RBP)。体系结构通过将使用REX前缀的指令的高字节引用(AH、BH、CH、DH)更改为低字节引用(BPL、SPL、DIL、SIL、SIL:RBP、RSP、RDI和RSI的低8位),来加强这一限制。


在64位模式下,操作数大小确定目标通用寄存器中的有效位数:


  • 64位操作数在目标通用寄存器中生成一个64位的结果。
  • 32位操作数生成一个32位结果,在目标通用寄存器中将零扩展到一个64位结果。
  • 8位和16位操作数将生成一个8位或16位的结果。目标通用寄存器的上56位或48位(分别)不被该操作修改。如果8位或16位操作的结果打算用于64位地址计算,则显式地签名将寄存器扩展到完整的64位。

由于64位通用寄存器的上32位在32位模式中未定义,因此当从64位模式切换到32位模式(切换到保护模式或兼容模式)时,任何通用寄存器的上32位都不被保留。软件不能在64位到32位的模式切换后依赖这些位来维持一个值。


段寄存器

段寄存器(CS、DS、SS、ES、FS和GS)保持16位段选择器。段选择器是标识内存中的段的特殊指针。要访问内存中的特定段,该段的段选择器必须位于相应的段寄存器中。


在编写应用程序代码时,程序员通常使用汇编程序指令和符号创建段选择器。汇编程序和其他工具然后创建与这些指令和符号相关联的实际段选择器值。如果编写系统代码,程序员可能需要直接创建段选择器。请参见Intel®64和IA-32架构软件开发人员手册第3A卷中的第3章"受保护模式的内存管理"。


如何使用段寄存器取决于操作系统或执行使用的内存管理模型的类型。使用平面(未分段)内存模型时,段寄存器加载指向重叠段的段选择器,每个段从线性地址空间的地址0开始(见图3-6)。这些重叠的段然后包括程序的线性地址空间。通常,定义了两个重叠的段:一个用于代码,另一个用于数据和堆栈。CS段寄存器指向代码段,所有其他段寄存器指向数据和堆栈段。


使用分段存储器模型时,每个段寄存器通常加载不同的段选择器,以便每个段寄存器指向线性地址空间内的不同段(见图3-7)。在任何时候,程序都可以访问线性地址空间中的六个段。要访问段寄存器之一未指向的段,程序必须首先加载段选择器,以便将要访问的段加载到段寄存器中。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FHcPpQ88-1622795531763)(RackMultipart20210604-4-42zeu4_html_eca9bdfa3ca4928.png)]

20210604163941962.png

图3-6 平面内存模型中段寄存器的使用


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zyLMyKYS-1622795531763)(RackMultipart20210604-4-42zeu4_html_6a4eb2c714fc6b4c.png)]

20210604163947257.png

图3-7 在分段内存模式下使用分段寄存器


每个段寄存器都与三种存储类型中的一种相关联:代码、数据或堆栈。例如,CS寄存器包含代码段的段选择器,其中存储被执行的指令。处理器使用由CS寄存器中的段选择器和EIP寄存器的内容组成的逻辑地址从代码段获取指令。EIP寄存器包含下一个要执行的指令的代码段中的偏移量。应用程序不能显式地加载CS寄存器。相反,它通过更改程序控制的指令或内部处理器操作(如过程调用、中断处理或任务切换)隐式加载。


DS、ES、FS和GS寄存器指向四个数据段。四个数据段的可用性允许高效和安全地访问不同类型的数据结构。例如,可以创建四个独立的数据段:一个用于当前模块的数据结构,另一个用于从高级模块导出的数据,第三个用于动态创建的数据结构,第四个用于与另一个程序共享的数据。要访问其他数据段,应用程序必须根据需要将这些段的段选择器加载到DS、ES、FS和GS寄存器中。


SS寄存器包含堆栈段的段选择器,其中过程堆栈为当前正在执行的程序、任务或处理程序存储过程堆栈。所有的堆栈操作都使用SS寄存器来查找该堆栈。与CS寄存器不同,SS寄存器可以显式地加载,这允许应用程序设置多个堆栈并在它们之间切换。


有关如何在实际地址模式中使用段寄存器的概述,请参阅第3.3节"内存组织"。


四个段寄存器CS、DS、SS和ES与Intel8086和Intel286处理器中的段寄存器相同,并将Intel386™系列处理器引入IA-32体系结构中。


64位模式下的段寄存器

在64位模式下:CS、DS、ES、SS被认为每个段基地址为0,而不管相关段描述符基的值如何。这将为代码、数据和堆栈创建一个平面地址空间。FS和GS都是例外。两个段寄存器都可用作线性地址计算中的附加基寄存器(在本地数据和某些操作系统数据结构的寻址)。


即使通常禁用分割,段寄存器加载也可能导致处理器执行段访问辅助。在这些活动期间,已启用的处理器仍将对已加载的值执行大部分遗留检查(即使这些检查在64位模式下不适用)。需要这样的检查,因为在兼容模式下运行的段寄存器可以使用64位模式下运行的应用。


在64位模式下,将禁用对CS、DS、ES、SS、FS和GS的限制检查。


EFLAGS寄存器

32位EFLAGS寄存器包含一组状态标志、一个控制标志和一组系统标志。图3-8定义了此寄存器内的标志。初始化处理器后(通过确认RESET管脚或INIT管脚),EFLAGS寄存器的状态为00000002H。保留此寄存器的第1、3、5、15和22至31位。软件不应该使用或依赖于任何这些位的状态。


可以使用特殊用途指令(以下部分中的说明)直接修改EFLAGS寄存器中的一些标志。没有任何指令允许直接检查或修改整个寄存器。


以下说明可用于将标志组移到过程堆栈或EAX寄存器之间:LAHF、SAHF、PUSHF、PUSHFD、POPF和POPFD。在EFLAGS寄存器的内容转移到过程堆栈或EAX寄存器之后,可以使用处理器的位操作指令(BT、BTS、BTR和BTC)来检查和修改标志。


挂起任务(使用处理器的多任务处理功能)时,处理器会自动将EFLAGS寄存器的状态保存在任务状态段(TSS)中,以便于挂起的任务。当将自己绑定到新任务时,处理器使用来自新任务的TSS的数据加载EFLAGS寄存器。


当调用中断或异常处理程序过程时,处理器会自动在过程堆栈中保存EFLAGS寄存器的状态。当使用任务开关处理中断或异常时,EFLAGS寄存器的状态将保存在TSS中以执行待暂停的任务。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uhnveb8x-1622795531764)(RackMultipart20210604-4-42zeu4_html_a751b5d70f8ebdd2.png)]


20210604164004985.png

图3-8 EFLAGS寄存器


随着IA-32体系结构的发展,标志已经被添加到EFLAGS寄存器中,但现有标志从一个IA-32处理器家族的功能和位置一直保持不变。因此,为一个IA-32处理器族访问或修改这些标志的代码在以后的处理器族上运行时可以按预期工作。


状态标志

EFLAGS寄存器的状态标志(位0、2、4、6、7和11)指示算术指令的结果,如ADD、SUB、MUL和DIV指令。状态标志功能包括:


CF (bit 0)


进位标志—如果算术运算从结果的显著位生成进位或借位,则设置;否则将清除。此标志表示无符号整数运算的溢出条件。它也被用于多精度算术。


PF (bit 2)


奇偶校验标志—如果结果的最小重要字节包含1位的偶数,则设置;否则将清除。


AF (bit 4)


辅助携带标志—如果算术操作从第3位获取结果,则设置;否则将清除。此标志用于二进制编码的十进制数(BCD)算法。


ZF (bit 6)


零标志-如果结果为零,则设置,否则将清除。


SF (bit 7)


符号标志—设置为等于结果中最重要的位,即有符号整数的符号位。(0表示正值,1表示负值。)


OF (bit 11)


溢出标志—如果整数结果太大、正数或负数太小(不包括符号位),无法适合目标操作数时设置;否则将清除。此标志表示有符号整数(两个补数)算术的溢出条件。


在这些状态标志中,只能使用STC、CLC和CMC指令直接修改CF标志。此外,位指令(BT、BTS、BTR和BTC)也将可以指定的位复制到CF标志中。


状态标志允许单个算术运算生成三种不同数据类型的结果:无符号整数、有符号整数和BCD整数。如果算术运算的结果视为无符号整数,CF标志表示超限条件(携带或借);如果视为有符号整数(两个补号),OF标志表示携带或借;如果视为BCD数字,AF标志表示携带或借。SF标志表示一个有符号整数的符号。ZF标志表示有符号整数或无符号整数零。


当对整数执行多精度运算时,CF标志与加带(ADC)一起使用,与借(SBB)指令一起进行减法,以便从一个计算传播到下一个计算。


条件指令Jcc(跳转条件代码cc)、SETCc(根据条件代码cc设置字节)、LOOPCC和CMOVCC(条件移动)使用一个或多个状态标志作为条件代码,并测试其分支、setbyte或结束循环条件。


DF标志

方向标志(DF,位于EFLAGS寄存器的位10中)控制字符串指令(MOVS、CMPS、SCAS、LODS和STOS)。设置DF标志会导致字符串指令自动递减(处理从高地址到低地址的字符串)。清除DF标志会导致字符串指令自动递增(处理字符串从低地址添加到高地址)。


STD和CLD指令分别设置并清除DF标志


系统标志和IOPL字段

EFLAGS寄存器控制操作系统或执行操作中的系统标志和IOPL字段。它们应该不能被应用程序修改。系统标志的功能如下:


TF (bit 8)


陷阱标志—设置为启用单步调试模式;清除为禁用单步模式。


IF (bit 9)


中断启用标志—控制处理器对可屏蔽的中断请求的响应。设置为响应可屏蔽中断;已清除以阻止可屏蔽中断。


IOPL (bits 12 and 13)


输入/输出权限级别字段—表示当前正在运行的程序或任务的输入/输出权限级别。当前正在运行的程序或任务的当前权限级别(CPL)必须小于或等于I/O权限级别,才能访问I/O地址空间。只有在0的CPL下操作时,POPF和IRET指令才能修改此字段。


NT (bit 14)


嵌套的任务标志—控制已中断和被调用的任务的链接。在当前任务链接到先前执行的任务时设置;在当前任务未链接到其他任务时清除。


RF (bit 16)


恢复标志—控制处理器对调试异常的响应。


VM (bit 17)


虚拟8086模式标志—设置为启用虚拟8086模式;清除以返回到没有虚拟8086模式语义的受保护模式。


AC (bit 18)


对齐检查(或访问控制)标志—如果在CR0寄存器中设置了AM位,则当且仅当此标志为1时,才会启用用户模式数据访问的对齐检查。


如果在CR4寄存器中设置了SMAP位,则当且仅当该位为1时,才允许显式监督模式数据访问用户模式页面。请参见Intel®64和IA-32架构软件开发人员手册第3A卷中的第4.6节"访问权限"。


VIF (bit 19)


虚拟中断标志—IF标志的虚拟映像。与VIP标志一起使用。(若要使用此标志和VIP标志,可通过在控制寄存器CR4中设置VME标志来启用虚拟模式扩展。)


VIP (bit 20)


虚拟中断挂起标志—设置为指示中断正在挂起;未挂起中断时清除。(软件设置并清除此标志;处理器只读取它。)与VIF标志一起使用。


ID (bit 21)


标识标志—程序设置或清除此标志的能力表示支持CPUID指令。


有关这些标志的详细说明:请参阅Intel®64和IA-32架构软件开发人员手册第3A卷中的第3章"保护模式内存管理"。


RFLAGS在64位模式下的寄存器

在64位模式下,EFLAGS被扩展到64位,并被称为RFLAGS。保留了上32位的RFLAGS寄存器位。较低的32位的RFLAGS与EFLAGS相同。


指令指针

指令指针(EIP)寄存器包含当前代码段中要执行的下一个指令的偏移量。它在直线代码中从一个指令边界推进到下一个指令边界,或者在执行JMP、Jcc、CALL、RET和IRET指令时被许多指令向前或向后移动。


EIP寄存器不能通过软件直接访问;它由控制传输指令(如JMP、JcC、CALL和RET)、中断和异常进行隐式控制。读取EIP寄存器的唯一方法是执行一个CALL指令,然后从过程堆栈中读取返回指令指针的值。可以通过修改过程堆栈上的返回指令指针的值并执行返回指令(RET或IRET)来间接加载EIP寄存器。请参见第6.2.4.2节,"返回指令指针"。


所有IA-32处理器都预取指令。由于指令预取,在指令加载期间从总线读取的指令地址与EIP寄存器中的值不匹配。尽管不同的处理器一代使用不同的预取机制,但EIP寄存器引导程序流的功能仍然与所有编写的在IA-32处理器上运行的软件完全兼容。


64位模式下的指令指针

在64位模式下,RIP寄存器成为指令指针。该寄存器保存下一个要执行的指令的64位偏移量。64位模式还支持一种被称为RIP相对寻址的技术。使用这种技术,通过向下一条指令的RIP添加一个置换来确定有效地址。


操作数的大小和地址的大小的属性

当处理器在受保护模式下执行时,每个代码段都具有默认的操作数大小属性和地址大小属性。这些属性通过代码段段描述符中的D标记(默认大小)(参见Intel®64和IA-32体系结构软件开发人员手册第3A卷第3章"保护模式内存管理")。当设置D标志时,将选择32位操作数大小和地址大小属性;当标志被清除时,将选择16位大小属性。当处理器在实际地址模式、虚拟8086模式或SMM下执行时,默认的操作数大小和地址大小属性始终为16位。


这个操作数大小属性将决定操作数的大小。当16位操作数大小属性有效时,操作数通常可以是8位或16位,而当32位操作数大小属性有效时,操作数通常可以是8位或32位。


地址大小属性选择用于地址内存的地址大小:16位或32位。当16位地址大小属性有效时,段偏移和位移为16位。此限制将数据段的大小限制为64K字节。当32位地址大小属性有效时,段偏移和位移为32位,允许最多处理4G字节。


通过在指令中添加操作数大小和/或地址大小的前缀,可以覆盖特定指令的默认操作数大小属性和/或地址大小属性。请参见Intel®64和IA-32架构软件开发人员手册第2A卷中的第2章"说明格式"。此前缀的效果仅适用于目标指令。


表3-4显示了有效的操作数大小和地址大小(在保护模式或兼容模式下执行时),具体取决于D标志的设置以及操作数大小和地址大小前缀的设置。


表3-3 有效的操作符和地址大小的属性


代码段描述符中的D标志 0 0 0 0 1 1 1 1

操作符大小的前缀66H N N Y Y N N Y Y

地址大小的前缀67H N Y N Y N Y N Y

有效的操作数大小 16 16 32 32 32 32 16 16

有效的地址大小 16 32 16 32 32 16 32 16

备注:Y,有这个指令前缀。N:不存在,不存在此指令前缀。


64位模式下的操作员大小和地址大小

在64位模式下,默认地址大小为64位,默认操作数大小为32位。可以使用前缀覆盖默认值。地址大小和操作数大小的前缀允许在逐个指令的基础上混合32/64位数据和32/64位地址。表3-4显示了66H指令前缀和REX的有效组合。可用来在64位模式下指定操作数大小覆盖的W前缀。请注意,在64位模式下不支持16位地址。


REX前缀由形成16个不同值的4位字段组成。REX前缀中的W位字段称为REX。W.,如果是REX。W字段设置正确,前缀指定操作数大小覆盖为64位。请注意,软件仍然可以使用操作数大小的66H前缀来切换到16位操作数大小。但是,请设置REX。使用操作时,W优先于操作数大小前缀(66H)。


对于SSE/SSE2/SSE3/SSSE3SIMD指令:66H、F2H和F3H操作码扩展必须前缀。在这种情况下,有效的REX之间没有交互。W的前缀和一个66H的操作码扩展前缀。


请参见Intel®64和IA-32架构软件开发人员手册第2A卷中的第2章"说明格式"。


表3-4 64位模式下的有效操作符和地址大小属性


代码段描述符中的L个标志 1 1 1 1 1 1 1 1

REX.W前缀 0 0 0 0 1 1 1 1

操作数大小的前缀66H N N Y Y N N Y Y

地址大小的前缀67H N Y N Y N Y N Y

有效的操作数位数 32 32 16 16 64 64 64 64

有效的地址位数 64 32 64 32 64 32 64 32

备注:Y,有这个指令前缀。N:不存在,不存在此指令前缀。


操作数寻址

IA-32机器指令作用于零或多个操作数。一些操作数是显式指定的,而另一些则是隐式指定的。源操作数的数据可以位于:


  • 指令本身(一个直接操作数)
  • 寄存器
  • 内存位置
  • 输入、输出端口

当指令将数据返回到目标操作数时,它可以返回到:


  • 寄存器
  • 内存位置
  • 输入、输出端口

立即数操作

有些指令使用在指令本身中编码的数据作为源操作数。这些操作数被称为立即数(或简称直接操作数)。例如,以下ADD指令向EAX寄存器的内容添加即时值14:


ADD EAX, 14


所有算术指令(除DIV和IDIV指令外)都允许源操作数为直接值。直接操作数所允许的最大值随指令而变化,但永远不能大于无符号双字整数(232)的最大值。


寄存器操作

源操作数和目标操作数可以是以下任何一个寄存器,具体取决于正在执行的指令:


  • 32位通用寄存器(EAX、EBX、ECX、EDX、ESI、EDI、ESP或EBP)
  • 16位通用寄存器(AX、BX、CX、DX、SI、DI、SP或BP)
  • 8位通用寄存器(AH、BH、CH、DH、AL、BL、CL或DL)
  • 段寄存器(CS、DS、SS、ES、FS和GS)
  • EFLAGS寄存器
  • x87 FPU寄存器(ST0至ST7、状态字、控制字、标签字、数据操作数指针和指令指针)
  • MMX寄存器(MM0至MM7)
  • XMM寄存器(XMM0到XMM7)和MXCSR寄存器
  • 控制寄存器(CR0、CR2、CR3和CR4)和系统表指针寄存器(GDTR、LDTR、IDTR和任务寄存器)
  • 调试寄存器(DR0、DR1、DR2、DR3、DR6和DR7)
  • MSR寄存器

一些指令(如DIV和MUL指令)使用包含在一对32位寄存器中的四字操作数。寄存器对用一个冒号分隔它们来表示。例如,在寄存器对EDX:EAX中,EDX包含高阶位,而EAX包含四字操作数的低阶位。


提供了多个指令(如PUSHFD和POPFD指令)来加载和存储EFLAGS寄存器的内容,或设置或清除此寄存器中的单个标志。其他指令(如Jcc指令)使用EFLAGS寄存器中的状态标志的状态作为分支或其他决策操作的条件代码。


处理器包含一些系统寄存器,用于控制内存管理、中断和异常处理、任务管理、处理器管理和调试活动。其中一些系统寄存器可以通过应用程序、操作系统或执行器通过一组系统指令来访问。当使用系统指令访问系统寄存器时,该寄存器通常是该指令的一个隐含操作数。


在64位模式下的寄存器操作数

在64位模式下的寄存器操作数可以是以下内容之一:


  • 64位通用寄存器(RAX、RBX、RCX、RDX、RSI、RDI、RSP、RBP或R8-R15)
  • 32位通用寄存器(EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP或R8D-R15D)
  • 16位通用寄存器(AX、BX、CX、DX、SI、DI、SP、BP或R8W-R15W)
  • 8位通用寄存器:AL、AL、BL、CL、DL、SIL、SPL和R8B-R15B;AL、BL、CL、DL、AH、BH、CH、不使用REX前缀的DH。
  • 段寄存器(CS、DS、SS、ES、FS和GS)
  • RFLAGS寄存器
  • x87FPU寄存器(ST0至ST7、状态字、控制字、标签字、数据操作数指针和指令指针)
  • MMX寄存器(MM0至MM7)
  • XMM寄存器(XMM0到XMM15)和MXCSR寄存器
  • 控制寄存器(CR0、CR2、CR3、CR4和CR8)和系统表指针寄存器(GDTR、LDTR、IDTR和任务寄存器)
  • 调试寄存器(DR0、DR1、DR2、DR3、DR6和DR7)
  • MSR寄存器
  • RDX:表示128位操作数的RAX寄存器对

内存操作

内存中的源操作数和目标操作数通过段选择器和偏移量进行引用(参见图3-9)。段选择器指定包含该操作数的段。偏移量指定操作数的线性地址或有效地址。偏移量可以为32位(由符号m16:32表示)或16位(由符号m16:16表示)。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CleLL28Q-1622795531764)(RackMultipart20210604-4-42zeu4_html_199c0503fc4d6db2.png)]

20210604164018914.png

图3-9 内存操作地址


64位模式下的内存操作数

在64位模式下,存储器操作数可以由段选择器和偏移量来引用。偏移量可以为16位、32位或64位(见图3-10)。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ouVnPFrZ-1622795531765)(RackMultipart20210604-4-42zeu4_html_385ebef090f300e8.png)]

2021060416403324.png

图3-10 64位模式下的内存操作员地址


指定一个数据段选择器

可以隐式地或显式地指定线段选择器。指定段选择器的最常见的方法是将其加载到段寄存器中,然后允许处理器根据所执行的操作的类型隐式地选择寄存器。处理器会根据表3-5中给出的规则自动选择一个数据段。


在存储器中存储数据或从内存中加载数据时,可以覆盖DS段默认值以允许访问其他段。在汇编程序中,段覆盖通常使用冒号":"操作符来处理。例如,以下MOV指令将一个值从寄存器EAX移动到ES寄存器所指向的段中。该段中的偏移量包含在EBX寄存器中:


MOV ES:[EBX], EAX


表3-5 默认段寄存器选择规则


类型 寄存器使用 使用段 默认选择规则

指令 CS 代码段 所有指令的获取量

栈 SS 堆栈段 所有的堆栈都会推送和弹出。使用ESP或EBP寄存器作为基寄存器的任何内存引用

局部数据 DS 数据段 所有数据引用,但相对于堆栈或字符串目标时除外。

目标字符串 ES 与ES寄存器一起指向的数据段 字符串指令的目标。

在机器级别,用段覆盖前缀指定一个放置在指令开头的字节。无法覆盖以下默认数据段选择:


  • 必须从代码段中获取指令
  • 字符串指令中的目标字符串必须存储在ES寄存器所指向的数据段中。
  • 推入和弹出操作必须始终参考SS段。

有些指令要求显式地指定数据段选择器。在这些情况下,16位段选择器可以位于存储器位置或16位寄存器中。例如,以下MOV指令将位于寄存器BX中的段选择器移动到段寄存器DS中:


MOV DS, BX


段选择器也可以显式地指定为内存中48位远距离指针的一部分。在这里,内存中的第一个双字包含偏移量,下一个字包含数据段选择器。


在64位模式下的段分割

在IA-32e模式下,分割的效果取决于处理器是在兼容模式还是64位模式下运行。在兼容模式下,分割功能与传统的IA-32模式一样,使用上述16位或32位保护模式语义。


在64位模式下,分割通常(但不是完全)被禁用,从而创建一个平坦的64位线性地址空间。处理器将CS、DS、ES、SS的段基视为零,创建一个等于有效地址的线性地址。例外是FS和GS段,它们的段寄存器(保持段基)可以作为某些线性地址计算中的附加基寄存器。


指定一个偏移量

内存地址的偏移部分可以直接指定为静态值(称为偏移),或者通过由以下一个或多个组件组成的地址计算:


  • 位移—一个8位、16位或32位的值。
  • 基数—一个通用寄存器中的值。
  • 索引-通用寄存器中的值。
  • 比例因子—一个由2、4或8组成的值乘以索引值的值。

添加这些组件所产生的偏移量称为有效地址。除比例因子外,每个组件都可以具有正值或负值(2s补值)。图3-11显示了将这些组件组合在选定段中创建有效地址的所有可能方法。


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hn7I5zLa-1622795531766)(RackMultipart20210604-4-42zeu4_html_3bc38f668b3c1186.png)]

20210604164053692.png

图3-11 偏移量(或有效地址)的计算


通用寄存器作为基础或索引组件的使用受到如下限制:


  • ESP寄存器不能用作索引寄存器。
  • 当ESP或EBP寄存器用作基础时,SS段为默认段。在所有其他情况下,DS段都是默认段。

基础、索引和位移组件可以以任何组合使用,这些组件中的任何一个都可以为空。只有在也使用了索引时,才能使用比例因子。每种可能的组合对于程序员在高级语言和汇编语言中通常使用的数据结构都很有用。


以下寻址模式建议用于地址组件的常见组合。


  • 位移⎯单独位移表示操作数的直接(未计算)偏移。因为位移是在指令中编码的,所以这种形式的地址有时被称为绝对地址或静态地址。它通常用于访问一个静态分配的标量操作数。
  • 基本⎯单独基本表示对操作数的间接偏移。由于基寄存器中的值可以更改,因此可以用于变量和数据结构的动态存储。
  • 基+位移⎯这种组合的一个重要特殊情况是访问过程激活记录中的参数。过程激活记录是在输入过程时创建的堆栈帧。在这里,EBP寄存器是基寄存器的最佳选择,因为它会自动选择堆栈段。这是这个通用函数的一个紧凑的编码。基寄存器和位移可一起用于两个不同的用途:
  • 当元素大小不是2、4或8字节时,作为索引—位移组件将静态偏移编码到数组的开头。基寄存器保存计算结果,以确定对数组中特定元素的偏移量。
  • 访问记录的字段:基本寄存器保留记录的起始地址,而位移是对该字段的静态偏移。
  • (索引∗Scale)+位移⎯当元素大小为2、4字节或8字节时,此地址模式可以有效地将其索引为静态数组。位移定位数组的开始,索引寄存器保存所需数组元素的下标,并且处理器通过应用缩放因子自动将下标转换为索引。
  • 基本+Index+位移⎯使用两个寄存器一起支持二维数组(位移保留数组开头的地址)或记录数组的几个实例之一(位移是对记录内字段的偏移)。
  • Base+(Index∗Scale缩放)+位移⎯将所有寻址组件一起使用,当数组的元素大小为2、4或8字节时,可以对二维数组进行有效的索引。

在64位模式下指定一个偏移量

64位模式下的存储器地址的偏移部分可以直接指定为静态值或通过由以下一个或多个组件组成的地址计算:


  • 位移—一个8位、16位或32位的值。
  • Base—64位通用寄存器中的值。
  • 索引—一个64位通用寄存器中的值。
  • 比例因子—一个由2、4或8组成的值乘以索引值的值。
  • 在大多数情况下,可以在16个可用的通用寄存器中的一个中指定基值和索引值。请参见Intel®64和IA-32架构软件开发人员手册第2A卷中的第2章"说明格式"。还提供了以下地址组件的唯一组合。
  • RIP+位移⎯在64位模式下,RIP相对寻址使用签名32位位移通过符号扩展32位值并添加到64位值的RIP来计算下一条指令的有效地址。

汇编程序和编译器寻址模式

在机器代码级别,选定的位移、基本寄存器、索引寄存器、缩放器和比例因子的组合将在指令中编码。所有汇编程序都允许程序员使用这些寻址组件的任何允许组合来处理操作数。高级语言编译器将根据程序员定义的语言构造来选择这些组件的适当组合。


输入输出端口地址

该处理器支持包含最多65,5368位I/O端口的I/O地址空间。在I/O地址空间中也可以定义16位和32位的端口。可以使用DX寄存器中的直接操作数或值来处理I/O端口。


相关文章
|
6月前
|
缓存 测试技术 数据中心
【计算机架构】计算 CPU 动态功耗 | 集成电路成本 | SPEC 基准测试 | Amdahl 定律 | MIPS 性能指标
【计算机架构】计算 CPU 动态功耗 | 集成电路成本 | SPEC 基准测试 | Amdahl 定律 | MIPS 性能指标
264 0
|
6月前
|
算法 编译器
【计算机架构】响应时间和吞吐量 | 相对性能 | 计算 CPU 时间 | 指令技术与 CPI | T=CC/CR, CC=IC*CPI
【计算机架构】响应时间和吞吐量 | 相对性能 | 计算 CPU 时间 | 指令技术与 CPI | T=CC/CR, CC=IC*CPI
339 0
|
6月前
|
存储 Linux Docker
跨cpu架构部署容器技术点:怎样修改Linux 的内核版本
在使用Docker 进行跨平台部署之后,我们还可以尝试进行跨架构部署。 从X86 架构上移植到 aarch64 上。
203 0
|
2天前
|
存储 人工智能 并行计算
计算机架构:漫游CPU的奥秘世界(二)
计算机架构:漫游CPU的奥秘世界
60 0
|
2天前
|
存储 人工智能 缓存
计算机架构:漫游CPU的奥秘世界(一)
计算机架构:漫游CPU的奥秘世界
65 0
|
2天前
|
存储 缓存 Linux
CPU高速缓存架构
CPU高速缓存架构
|
2天前
|
缓存 机器人 芯片
CPU_X86架构和ARM架构入门篇
CPU_X86架构和ARM架构入门篇
106 0
|
2天前
|
存储 编译器 数据处理
CPU架构和指令集
不同的CPU架构通常使用不同的指令集。每种CPU架构都有其自己的一组特定的机器指令,这些指令用于执行计算机程序。不同的CPU架构之间的指令集是不兼容的,这意味着编写的程序通常需要根据目标CPU的架构进行编译或汇编,以确保它们能够在该CPU上正确运行。 一些常见的CPU架构包括:
|
6月前
|
NoSQL Shell Linux
跨cpu架构部署容器技术点:怎么将容器启动时的1号进程挂载到systemctl
--privileged=true:是Docker中的一个参数,用于授予容器的特权权限。当一个容器被设置为特权容器时,它将拥有与主机操作系统相同的权限,可以执行一些高级操作,如访问主机设备、加载内核模块等。
47 0
|
9月前
|
Ubuntu
【Ubuntu系统如何查看 CPU 架构、系统信息、内核版本、版本代号?】
在 Ubuntu 中,我们可以使用一些命令来查看 CPU 架构、系统信息、内核版本、版本代号等相关信息。
874 0