运行模式

  • 实模式
  • 保护模式。32位处理器的主要模式。
  • 系统管理模式。
  • 虚拟8086模式
  • IA-32e模式。64位吃处理器的主要运行模式。

体系结构各运行模式间切换过程:

Screenshot_20220912_203300

处理器上电或重启之后首先运行实模式。CR0控制寄存器的PE标志位控制处理器运行在实模式或者保护模式。EFLAGS标志寄存器的VM标志位可使处理器在保护模式可使处理器在保护模式与虚拟8086模式间切换,切换过程往往通过任务切换或中断/异常返回程序实现。 在开启分页机制的保护模式下,置位IA32-EFER寄存器的LME标志位(位于IA32-EFER寄存器的第8位)可使处理器进入IA-32e模式。通过IA32-EFER寄存器的LMA标志位(位于IA32-EFER寄存器的第10位)可以判断处理器是否运行在IA-32e模式下。当前处理器运行与IA-32e模式,代码段描述符的L标志位可确定处理器运行于64位模式还是兼容模式。不管处理器正处于什么模式,一旦收到SMI信号便会进入SMM模式。只有在执行RSM指令后,处理器会返回到产生SMI信号前。

通用寄存器

IA32体系下的通用寄存器有EAXEBXECXEDXESIEDIEBPESPESP已被处理器用于保存栈指针值。

一些指令的执行必须依赖特定的寄存器。例如,ECXESIEDI寄存器经常用于字符串指令操作,DS段寄存器经常使用EBX寄存器来保存段内偏移地址。

Screenshot_20220912_211629

IA-32e体系结构的64位运行模式下,虽然通用寄存器的操作数模式是32位宽。但它们有能力支持64位宽的操作数。Intel公司在64位模式里加入了8个新的通用寄存器,因此处理器可使用RAXRBXRCXRDXRSIRBPRSPR8~R15这16个通用寄存器,其中的R8~R15寄存器只在64位模式下有效。

CPUID指令

CPUID指令用于鉴别处理器信息以及检测处理器支持的功能,它在任何模式下执行效果相同。通过EFLAGS标志寄存器的ID标志位(位于EFLAGS寄存器的第21位)可检测处理器是否支持CPUID指令。

CPUID指令使用EAX寄存器作为输入参数,也叫做主功能号。对于一些复杂的主功能来说,它可能会需要子功能号来辅助查询,此时ECX寄存器会向CPUID指令系统子功能号。CPUID指令执行结束后,CPUID指令会使用EAXEBXECXEDX寄存器保存执行结果。在64位模式下这些信息仍然是32位的,低32位有效,高32位清零。

CPUID指令可以查询两类信息:基础功能和扩展信息。基础信息主功能号从0h开始,目前处理器支持的最大主功能号是14h,处理器通过CPUID指令的主功能号0h可查询出处理器支持的最大基础功能号。扩展信息的主功能号从80000000h开始,目前处理器支持的最大主功能号是80000008h,处理器通过CPUID指令的主功能号80000000h可查询出处理器当前支持的最大扩展功能号。

Screenshot_20220912_213406

标志寄存器EFLAGS

EFLGAS标志寄存器包含有状态标志位、控制标志位以及系统标志位,处理器在初始化时将EFLGAS标志寄存器赋值为00000002h。在IA-32e体系结构中,EFLGAS标志寄存器已从32位扩展为64位,其中高32位暂时保留。

Screenshot_20220912_213731

某些特殊的汇编指令可以直接修改EFLGAS标志寄存器的标志位。指令LAHFSAHFPUSHFPUSHFDPOPFPOPFD可实现EFLAGS标志寄存器与栈(或EAX寄存器)的互相保存。一旦EFLGAS标志寄存器存有备份,程序便可以借助BTBTSBTRBTC等指令对标志位进行修改或检测。当程序通过调用门执行任务切换时,处理器会把EFLGAS标志寄存器值保存到任务状态段 TSS内,并将目标任务状态段TSS内的值更新到EFLGAS标志寄存器中。

状态标志

EFLGAS标志寄存器的状态标志(0、2、4、6、7、11位)可以反映汇编指令计算结果的状态,如ADDSUBMULDIV等汇编指令计算结果的奇偶性、溢出状态、正负值等。

Screenshot_20220912_214153

CF标志位可反映出有符号整型数计算结果的溢出状态,AF可反映BCD型整数计算结果的溢出状态,SF标志位可反映出有符号整型数计算结果的正负值,ZF标志位可反映整型数的计算结果。

以上标志位,只有CF标志位可通过STCCLCCMC汇编指令更改位值,它也可以借助位操作指令(BTBTSBTRBTC指令)将指定位值复制到CF标志位。而且CF标志位还可在多倍精度整型数计算时,结合ADC(含进位的加法计算)或SBB指令(含借位的减法指令)将进位计算或借位计算扩展到下次计算中。

至于状态跳转指令Jcc、状态字节置位指令SETcc、状态循环指令LOOPcc以及状态移动指令CMOVcc,它们可将一个或多个状态标志位作为判断条件,条件分支跳转、字节置位以及循环计数。

方向标志

DF方向标志位位于EFLAGS标志寄存器的第10位,它控制字符串指令(如MOVSCMPSSCASLODSSTOS等)的操作方向。置位DF标志位可使字符串指令按从高到低的地址方向(自减)操作数据,复位DF标志位可使字符串指令按从低到高的地址方向(自增)操作数据。汇编指令STDCLD可用于置位和复位DF方向标志位。

系统标志和IOPL区域

EFLAGS标志寄存器的系统标志和IOPL区域,负责控制I/O端口地址访问权限、屏蔽硬件中断请求、使能单步调试、任务嵌套以及使能虚拟8086模式等

Screenshot_20220912_221521

如果希望修改系统标志位或IOPL区域,则必须拥有足够的执行权限(0特权级)。VIFVIP标志只能在虚拟8086模式下有效;AC标志位只能对3特权级的数据对齐检测,如果发现数据未对齐则触发#AC异常;置位RF标志位将临时禁止断点触发#DB异常;IF标志位对NMI(Nonmaskable Interrupt,不可屏蔽中断)不起作用。可以借助汇编指令CLISTIPOPFPOPFDIRET操作IF标志位。

控制寄存器

控制寄存器功能表:

Screenshot_20220912_222012

IA-32体系结构下,控制寄存器位宽是32位,而IA-32e体系结构下位宽为64位

Screenshot_20220912_222118

可通过MOV CRn汇编指令可对控制寄存器进行操作,其中的保留位必须写入数值0,否则会触发#GP异常。CR2CR3寄存器不会对写入的地进行检测。CR8控制寄存器只在64位模式下有效。

各个有效标志位的功能说明:

Screenshot_20220912_222410

如果CR0.PE=0时,置位CR0.PG标志寄存器会触发#GP异常。CR0.CDCR0.NW标志位会联合控制处理器的缓存和读写策略。

Screenshot_20220912_222546

处理器的CR0.TSCR0.EM以及CR0.MP标志位都用于控制浮点处理器(x86 FPUMMXSSESSE2SSE3SSSE3SSE4等)的执行动作。

Screenshot_20220912_222740

标志位TSEMMPMMPSSESSE2SSE3SSSE3以及SSE4指令的影响会更复杂一些。

CRn控制寄存器和XCR0扩展控制寄存器(用于控制浮点计算功能)外,EFER寄存器也用于控制系统功能。它是MSR控制寄存器组的IA32_EFER寄存器,它提供了控制IA-32e运行模式开启的标志位,以及关于页表访问限制的控制区域。

Screenshot_20220912_223143

其中LME标志位最为重要,它用于开启IA-32e模式,而第0位则是SYSCALL/SYSRET指令的使能位。

Screenshot_20220912_223256

MSR寄存器组

MSR寄存器组可提供性能检测、运行轨迹跟踪与调试以及其他处理器功能。在使用MSR寄存器组之前,应该通过CPUID.01h:EDX[5]来检测处理器是否支持MSR寄存器组。每种处理器都有自己的MSR寄存器组,在使用MSR寄存器组前需要根据处理器的家族信息(CPUID.01h查询处理器家族信息)选择与相对应的MSR寄存器组。

处理器可以使用RDMSRWRMSR对MSR寄存器组进行访问,整个访问过程借助ECX寄存器索引寄存器地址,再由EDX:EAX组成的64位寄存器保存访问值。(64位模式下,RCXRAXRDX寄存器的高32位会被忽略)而且这对指令必须在实模式或0特权级下执行,否则将会触发#GP异常,使用MSR寄存器组的保留地址或无效地址都会产生通用保护异常。

通常IA32_EFER寄存器位于地址0c0000080h处,SYSENTER/SYSEXIT指令相关配置寄存器通常在地址174h175h176h处。这些寄存器地址可能根据处理器家族不同而变化。