x86 的解码通过查阅表格来工作。
如果给你一个你已经知道它是指令操作码(而不是指令前缀)的字节,并且该字节将保存值 B8h (10111000b),你会在它所代表的表中看到mov ax, imm16
。
opcode immediate
----------- --------------------
1011_1_000b, 00000011b, 00000000b
^ ^
| AX
w-bit
在您的第一个片段中,您尝试剖析 BBh (10111011b) 操作码,但如果您查阅相同的表,您会看到它代表mov bx, imm16
.
opcode immediate
----------- --------------------
1011_1_011b, 00000011b, 00000000b
^ ^
| BX
w-bit
但是,还有第二种方法可以mov ax, imm16
使用 modr/m 字节对指令进行编码,就像您在第一个代码段中尝试的那样:
opcode modr/m immediate
---------- ----------- --------------------
1100011_1b, 11_000_000b, 00000011b, 00000000b
^ ^ ^ ^
| | | r/m is AX
| | 000
| mod=11b => r/m is register
w-bit
此操作码没有 s 位;没有可用的符号扩展。因此,关心代码大小的汇编程序很少使用这种编码。
ADD
, ADC
, SUB
, SBB
, CMP
, AND
, OR
, XOR
, 和TEST
指令存在一对类似的编码。但是对于这些简短形式,没有 modr/m 字节的形式,仅适用于AX
寄存器。
您可以在https://software.intel.com/content/www/us/en/develop/articles/intel-sdm.html的英特尔手册中找到您需要的所有表格