-->

在16位模式操作数大小前缀(Operand size prefix in 16-bit mode)

2019-07-03 12:03发布

我想了解的.code16 GAS的行为。 从手动,似乎在16位部分中,32位操作数或指令,一个操作数66H覆盖前缀将为指令编码来产生。 这是否意味着

.code16
movw %eax, %ebx

就是在这样的模式是否合法? 然后代码不能在16位处理器上运行?

Answer 1:

这些是80386+的法律指导。 与80386,我们可以使用operandsize-和addresssize-覆盖前缀开始。 这些前缀可以组合使用与16位地址模式和与所述32位地址模式。 其他可与实际addressmode并与受保护模式和虚拟86模式下使用。 这些前缀扭转默认operandsize和/或用于在代码段一个指令的addresssize。 默认operandsize和addresssize由d标志在代码段描述符中指定(或如果没有GDT / LDT,则我们成为16位addressmode的BIOS POST-过程完成之后)。

随着16位addressmode我们要添加这些前缀,如果我们要使用32个操作数和/或32个地址。 如果没有这些前缀,我们只能在16位addressmode使用16位地址/操作数。

随着32位addressmode我们必须从我们的代码离开了这些前缀,如果我们要使用32个操作数和/或32个地址。 如果我们添加这些前缀到我们的代码,那么我们就可以在32位addressmode使用16位地址/操作数。

大段引用英特尔:

指令前缀可以用于覆盖一个代码段的默认操作数大小和地址大小。 这些前缀可以在实地址模式,以及在保护模式和虚拟8086模式下使用。 操作数大小或地址大小前缀仅更改指令的持续时间的大小。

以下两个指令前缀允许一个段内的32位和16位操作的混合:•操作数大小前缀(66H)•地址大小前缀(67H)

这些前缀逆转由d标志在代码段描述符选择的默认大小。 例如,处理器可以解释在任何的四种方式(MOV MEM,REG)指令:•在32位代码段:使用32位有效地址-Moves 32位从32位寄存器到存储器。 - 如果之前由操作数大小前缀,使用32位有效地址从一个16位寄存器,移动16位存储器。 - 如果之前由地址大小前缀,使用16位有效地址移动32位从32位寄存器到存储器。 -if之前通过两者地址大小前缀和操作数大小前缀,使用16位有效地址从一个16位寄存器,移动16位存储器。

•在16位的代码段:使用16位有效地址-Moves从16位寄存器16位到存储器。 - 如果之前由操作数大小前缀,使用16位有效地址移动32位从32位寄存器到存储器。 - 如果之前由地址大小前缀,使用32位有效地址从一个16位寄存器,移动16位存储器。 -if之前通过两者地址大小前缀和操作数大小前缀,使用32位有效地址移动32位从32位寄存器到存储器。

前面的实施例表明,任何指令可产生操作数大小和地址大小的任何组合,而不管对所述指令是否是在一个16位或32位的段。 的16位或32位的默认代码段的选择通常基于以下标准:•性能 - 始终可能时使用32位代码段。 他们跑的比对P6系列处理器的16位代码段快得多,并且在早期IA-32处理器有所加快。 •操作系统代码段将被运行 - 如果操作系统是一个16位操作系统,它可能不支持32位程序模块。 •操作模式 - 如果代码段正被设计成在实地址模式下运行,虚拟8086模式,或SMM,它必须是一个16位的代码段。 •向后兼容较早IA-32处理器 - 如果代码段必须能够在Intel 8086或Intel 286处理器上运行,它必须是一个16位的代码段。

在代码段描述符中的d标志确定为一个代码段的指令的默认操作数大小和地址大小。 (在实地址模式和虚拟8086模式,其不使用段描述符,默认值是16位。)与其d标志集代码段是一个32位的段; 以其d标志清除一个代码段是一个16位的段。

可执行代码段。 该标记被称为d标志,它表明用于通过在该段中引用的指令的有效地址和操作数的默认长度。 如果该标志被设置时,32位地址和32位或8位的操作数被假设; 如果它是清楚的,假定16位地址和16位或8位操作数。 指令前缀66H可以被用于选择默认值以外的操作数大小,并且前缀67H可以用于选择比默认以外的地址大小。

32位操作数前缀可以在实地址模式程序被用来执行指令的32位的形式。 这个前缀也允许实地址模式程序使用处理器的32位通用寄存器。 的32位地址前缀可以在实地址模式的程序一起使用,从而允许32位偏移。

与英特尔386处理器开始IA-32处理器可生成使用地址覆盖前缀32位偏移量; 然而,在实地址模式,一个32位的值的偏移量,而不会引起一个异常不得超过FFFFH。

汇编用法:如果是要在实地址模式运行代码段的定义,它必须被设置为使用16个属性。 如果一个32位操作数中的指令中使用在此代码段(例如,MOV EAX,EBX),汇编程序自动生成用于迫使处理器执行一个32位操作指令的操作数的前缀,即使其默认代码段属性是16比特。

32位操作数前缀允许实地址模式程序使用32位通用寄存器(EAX,EBX,ECX EDX,ESP,EBP,ESI,和EDI)。

当在32位模式下段寄存器和一个32位的通用寄存器之间移动数据,在Pentium Pro处理器不需要使用16位操作数大小前缀; 然而,某些汇编确实需要这个前缀。 处理器假定通用寄存器的16个最低显著位是目的地或源操作数。 当从段选择移动的值,以一个32位寄存器,所述处理器用零填充寄存器的两个高位字节。

大段引用AMD:

3.3.2。 32位与16位地址和操作数大小的处理器可以被配置为32位或16位的地址和操作数大小。 具有32位地址和操作数大小,偏移最大线性地址或段是FFFFFFFFH(2 ^ 32-1),和操作数大小是通常为8位或32位。 具有16位地址和操作数大小,偏移最大线性地址或段是FFFFH(2 ^ 16-1),和操作数大小是通常为8位或16位。 当使用32位寻址,一个逻辑地址(或远指针)由16位段选择器和一个32位的偏移; 使用16位寻址的情况下,它由一个16位的段选择的和16位偏移。 指令前缀允许从程序中的默认地址和/或操作数大小的临时覆盖。 当在保护模式下运行时,对于当前正在执行的代码段的段描述符定义了默认地址和操作数大小。 段描述符是一个系统的数据结构不正常至应用程序代码可见。 汇编指令允许默认寻址和操作数的大小,被选中的程序。 汇编器和其他工具,然后设置为代码段段描述恰如其分。 当在实地址模式中操作时,默认寻址和操作数大小是16位。 地址大小覆盖可在实地址模式被用来使32位寻址; 然而,最大可允许的32位线性地址仍然是000FFFFFH(2 ^ 20-1)。

3.6。 操作数大小和地址尺寸属性。当处理器在保护模式下执行,每一个代码段具有默认操作数大小属性和地址大小属性。 这些属性与该段描述符代码段d(默认大小)标志选择(见第3章,保护模式的内存管理,在英特尔架构软件开发人员手册,第3卷)。 当d标志被设置,在32位操作数大小和地址尺寸属性被选择; 当标志是明确的,16位的尺寸属性被选择。 当处理器在实地址模式下执行,虚拟8086模式,或SMM(系统管理模式)时,默认操作数大小和地址尺寸属性总是16位。 操作数大小属性选择该指令操作的操作数上的尺寸。 当16位的操作数大小属性生效时,操作数可以通常为8个位或16位,并且当在32位操作数大小属性生效时,操作数可以通常为8位或32位。 地址大小属性选择用于地址的存储器地址的大小:16位或32位。 当16位的地址大小属性的有效期内,段偏移和位移是16位。 这种限制限制了可以寻址到64K字节的段的大小。 当32位的地址大小属性的有效期内,段偏移和位移32位,允许多达4千兆字节的段要处理。 默认数大小属性和/或地址大小属性,可以通过添加数大小和/或地址尺寸前缀的指令(见“指令前缀”在英特尔架构软件的第2章覆盖特定指令开发人员手册,第3卷)。 这个前缀的作用仅适用于它连接到的指令。 表3-1示出了根据所述d标志的设置,操作数大小和地址大小前缀有效操作数大小和地址大小(在保护模式下执行时)。

短剑



文章来源: Operand size prefix in 16-bit mode