我们如何在16位中使用`e [] x`而在32位中不使用`r [] x`

时间:2012-08-19 23:04:08

标签: assembly x86 x86-64

所以在汇编中,我们如何在16位实模式中使用e[]x,但我们不能在32位模式下使用r[]x?例如:

BITS 16
mov bx, 1
mov eax, 2

将正确地在IDA中组装和反汇编(在16位模式下)。它起作用,因为我之前已经拆解了Win2k引导程序并找到了eax的引用。

但是,即使在保护模式下的64位处理器上也无法访问r[]x

3 个答案:

答案 0 :(得分:4)

原因是64位模式在一个特定的地方改变指令解码 - 即,启用用于指示64位操作数大小的前缀字节/扩展寄存器宽度到64位/扩展寄存器用于“新”R8 .. R15寄存器。这些与“备用大小前缀”(0x66)不同,后者是x86的通用(独立于CPU操作模式),如果在16位模式下,操作数/寄存器大小从16位更改为32位,反之亦然如果处于32位模式,则为32位至16位。

如果CPU在64位模式下运行,则所谓的REX前缀编码为0x40 .. 0x4f,并且 作为前缀有效。为什么会这样 ?好吧 - 如上所述,改变了指令解码,这些操作码实际上映射到经典x86中的inc <reg> / dec <reg>的单字节版本。
这是可能的,因为16 / 32bit指令集中的含糊不清 - inc EAX可以 <{em> 0x40 0xff 0xc0。在64位模式下,指令解码器仅接受0xff 0xc0。另一方面,0x40,如所示,成为REX前缀之一。

因此 - 这些64位操作数大小的前缀在16位/ 32位模式下不存在(它们是inc / dec操作然后...),因此不存在用16bit / 32bit x86代码表示“我想做64位操作”。

举个例子,这里是一些具有不同操作数大小的指令的汇编/操作码:

      64bit   32bit option 1   32bit option 2     instruction
=============================================================
      fe c8            fe c8               --     dec    al
   66 ff c8         66 ff c8            66 48     dec    ax
      ff c8            ff c8               48     dec    eax
   48 ff c8               --               --     dec    rax

正如您所看到的,64位不知道dec eax的单字节版本,而是知道0x48作为(几个中的一个)指令前缀,说“使这个为64位操作”

答案 1 :(得分:2)

好吧,如果你使用的是80286,那么它就行不通了!您使用的计算机是32位CPU,具有16位和32位寄存器但不是64位寄存器。它也适用于64位cpu。

答案 2 :(得分:1)

通过设计,CPU设计,您无法在非64位模式下访问64位寄存器。

您也可以通过设计访问16位模式的32位寄存器。您可以使用名为operand size prefixaddress size prefix的特殊指令前缀来执行此操作。在非64位模式下,没有特殊的指令前缀可以达到64位寄存器。