assembly - 为什么我们可以在16位模式下使用eRx,而在32位模式下不能使用rRx?

在x86汇编中,为什么我们可以在16位“实模式”下使用eRx,而不能在32位模式下使用rRx?例如:

BITS 16
mov bx, 1
mov eax, 2

将正确组装和拆卸。它工作正常,因为我之前反汇编了 Win2k 引导加载程序并找到了对 eax 的引用。

可是,怎么就没有办法,即使在64位处理器上,在32位“保护模式”下,也不能访问rRx

最佳答案

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

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

因此 - 这些 64 位操作数大小前缀在 16 位/32 位模式下不存在(它们是 inc/dec 操作然后...),因此 16 位/32 位 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 位操作”。

https://stackoverflow.com/questions/12030668/

相关文章:

vba - Access 自定义组

haskell - 包含不同类型的列表

php - 如何从一个函数返回多个值

sql-server - 普通的 SQL Server 索引是否包含主键值?

ruby-on-rails - 仅显示 f.label 覆盖 f.input 标签

mongodb - 为什么叫NoSQL?

php - 从php中的日期检索日期,月份,年份

unix - 用另一个值替换 unix 文件中的最后一列

encryption - 解码 AES-256 key 需要多少种组合?

sql - 更新引用另一个表