与早期的8位机器不同,如影响了8086设计决策的8080,对于大多数指令来说,两个操作数都是显式的,而不仅仅是由一个操作码隐含的。(后来x86的扩展包括一些具有两个以上操作数的指令,但x86仍然是mostly a 2-operand ISA。) 要进行比较,请参阅8080操作码Maphttps://pastraiser.com/cpu/i8080/i8080_opcodes.html 与x1E6 F1 x之类的8086操作码Map或x1E7 F1 x之类的表相比,(或者是现代的x86 32位模式操作码表http://ref.x86asm.net/coder32.html,它是最好的格式和可读的。)注意,在8080Map中,每个条目至少有一个目的地或者两个操作数都由操作码字节暗示。但是在8086中,通常只有助记符,其中操作数被单独编码。 因此,没有操作码和ModRM字节的组合可以将此指令表示为机器代码的字节序列。 请参阅 How to tell length of an x86 instruction?,查看x86机器码格式的总结图。(8086不允许SIB字节,因此寻址模式更有限,但所有其他可选部分仍然适用。8086只有1字节的操作码,从来没有2或3个,当然立即数和位移最多为2字节。
1条答案
按热度按时间q7solyqu1#
首先,
mov [ax], 0000h
不能用8086机器码来表示,它的目标寻址模式没有二进制表示。TL:DR:
mov
是助记符,[ax]
是目标操作数,0000h
是源操作数。没有二进制“opcode”,因为指令是不可编码的。但是如果你误用“opcode”来谈论源代码行的一部分,你通常会说mov
是操作码。**Opcodes是机器代码的特性,而不是汇编源代码。**也许他们是在歪曲术语来谈论指令名称,或者他们打算谈论它将如何汇编成机器代码。
在asm源代码
mov [ax],0000h
中:mov
是助记符,它说明了它是什么指令。这意味着机器代码将使用手册中列出的几个助记符之一(https://www.felixcloutier.com/x86/mov),汇编程序根据操作数进行选择。在这种情况下,内存目标和立即源,但两者都没有指定或暗示大小,因此可能是
C6 /0 ib
MOV r/m8, imm8
或C7 /0 iw
MOV r/m16, imm16
。emu 8086是doesn't warn you about the ambiguity in some cases的坏汇编程序,但在这里可能值为零。***
[ax]
是目的操作数.**无法用x86机器代码进行编码;它是not one of the few valid 16-bit invalid addressing modes。***
0000h
是源操作数。**大多数指令都有允许立即数源的操作码。与早期的8位机器不同,如影响了8086设计决策的8080,对于大多数指令来说,两个操作数都是显式的,而不仅仅是由一个操作码隐含的。(后来x86的扩展包括一些具有两个以上操作数的指令,但x86仍然是mostly a 2-operand ISA。)
要进行比较,请参阅8080操作码Maphttps://pastraiser.com/cpu/i8080/i8080_opcodes.html
与x1E6 F1 x之类的8086操作码Map或x1E7 F1 x之类的表相比,(或者是现代的x86 32位模式操作码表http://ref.x86asm.net/coder32.html,它是最好的格式和可读的。)注意,在8080Map中,每个条目至少有一个目的地或者两个操作数都由操作码字节暗示。但是在8086中,通常只有助记符,其中操作数被单独编码。
因此,没有操作码和ModRM字节的组合可以将此指令表示为机器代码的字节序列。
请参阅 How to tell length of an x86 instruction?,查看x86机器码格式的总结图。(8086不允许SIB字节,因此寻址模式更有限,但所有其他可选部分仍然适用。8086只有1字节的操作码,从来没有2或3个,当然立即数和位移最多为2字节。
如果它是
mov word ptr [si], 0000h
,机器码将是目的操作数
[si]
按ModRM字节编码,使用2位“mode”字段(0
)与3位“r/m”字段,前者指定无位移得内存寻址模式(因为它不是[si + 16]
或其他类型),后者仅指定si
.请参阅https://wiki.osdev.org/X86-64_Instruction_Encoding#16-bit_addressing或Intel或AMD手册中得表格.操作码是
c7
字节和ModRM字节的3位/r
字段(值为0
)。请参阅 * 如何读取英特尔操作码表示法 *,了解其工作原理的详细信息,从ModRM借用额外位作为额外操作码位。(这就是为什么我们有add ax, 123
这样的指令,而不是add cx, [si], 123
,它们具有只写目标和两个独立的源,包括操作码所暗示的立即数,因为ModRM通常可以像add cx, [si]
那样对两个操作数进行编码。只有imul cx, [si], 123
的新186格式允许这样做。类似地,neg dx
代替neg cx, dx
)如果它是
mov ax, 0000h
AX目标由前导字节的低3位指定。您可以将其视为8个不同的操作码字节,每个寄存器一个,并具有隐式目标。这种解释(对这条不同指令的解释,而不是作业中不可能的解释)与教师对操作码“mov-to-AX”的描述基本相符。
但实际上,您可能会说
mov ax, imm16
是操作码,填充占位符的实际值是0
操作数。8B /r
mov r16, r/m16
(例如:一个月三个月一个月)89 /r
mov r/m16, r16
(例如:一米三六英寸)A1
mov ax, moffs
(例如mov ax, [1234h]
)。具有绝对偏移量和AL或AX目标的特殊情况no-ModRM短格式。C7 /0 iw
mov r/m16, imm16
(例如,mov ax, 0
的更长编码)。8C /r mov r/m16, Sreg
(例如mov ax, ds
)。mov r/m16, cr0..7
(386中的新形式)和mov r/m16, dr0..7
(386),但控制寄存器直到286smsw
(存储机器状态字)才存在(?)。或者,您可以按照英特尔手册中的说明来理解它,
B8+ rw
iw
是MOV r16, imm16
的编码。因此,操作码是第一个字节的高5位,目标寄存器号是该字节的低3位。与内存目标形式一样,操作码本身暗示了16位立即数作为源操作数的存在。没有ModR/M字节;这些短格式编码的目的是为8086中的常见指令保存空间。还有类似的非ModRM短格式,如xchg-with-AX,
90h nop
来自xchg ax,ax
。以及用于完整寄存器的inc/dec。还有非ModRM短格式,用于大多数ALU与累加器的运算,例如add al, 123
是2字节,vs.add bl, 123
是3个字节。(请参阅x86机器码的程式码高尔夫秘诀)。注意,
mov ax, 0
* 也 * 可以用4字节编码,使用相同的mov r/m16, imm16
编码,用ModRM字节编码ax
寄存器作为目的地。汇编程序通常在有选择的情况下选择尽可能短的编码。(在某些情况下,有两个长度相同的选择,如add cx, dx
:请参见 * x86 XOR opcode differences *)