IA32 处理器有一个默认的代码大小,在 16 位代码段中(或在实模式下)是(猜测)16 位。在 32 位和 64 位代码段中是 32 位。
mov eax, 3ch 之类的指令实际上类似于 mov A, 3ch,其中 A 是 A 寄存器(RAX、RAX、AX)。
指令mov A, 3ch 编码为0b8h OPERAND_IN_LE,现在OPERAND_IN_LE 的代码大小为:16 位或32 位。
如果它是 16 位,那么您实际上是在写入 AX,如果它是 32 位,则写入 EAX。
所以0b8h 3ch 00 在 16 位中是 mov ax, 3ch,0b8h 3ch 00h 00h 00h 在 32 位中是 mov eax, 3ch。注意两条指令是相同的,CPU根据当前代码大小取16/32位操作数。
您可以使用数据大小前缀66h 覆盖默认代码大小。有了这个前缀,下一条指令的执行就像代码大小是“另一个”一样(即 16 位代码为 32 位,32 位代码为 16 位)。还有一个 REX 前缀可以访问完整的 64 位寄存器。
所以指令mov eax, 3ch在16位代码中被编码为66h 0b8h 3ch 00h 00h 00h,在32/64位代码中被编码为0b8h 3ch 00h 00h 00h。
为了完整起见,指令mov rax, 3ch 被编码为48h b8h 3ch 00h 00h 00h 00h 00h 00h 00h,并且只能在 64 位模式下使用。
您可以下载Intel Manual Vol2A,参考说明书及其从A到M的编码,包括mov。