所以在汇编中,我们如何在16位实模式中使用e[]x
,但我们不能在32位模式下使用r[]x
?例如:
BITS 16
mov bx, 1
mov eax, 2
将正确地在IDA中组装和反汇编(在16位模式下)。它起作用,因为我之前已经拆解了Win2k引导程序并找到了eax
的引用。
但是,即使在保护模式下的64位处理器上也无法访问r[]x
?
答案 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 prefix
和address size prefix
的特殊指令前缀来执行此操作。在非64位模式下,没有特殊的指令前缀可以达到64位寄存器。