assembly x86汇编源代码中的操作码与操作数

jw5wzhpr  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(592)

最近在一次考试中,当被问及操作码与操作数的关系时,我举了一个例子

mov [ax],0000h

我说mov是操作码,[ax],0000h是操作数,它们组成了一条指令。我的老师在这个问题上给了我一个0,说[ax]是操作码,0000h只是操作数。
在我的教科书中说,在MOV指令中,mov是操作码,源和目标通常称为操作数。
我想拿着课本去找我的老师再问一遍,但在我问之前,有人能帮我澄清一下吗?这样我就不会带着任何错误的理解进去了。
尝试写正确答案,得到0 lol。

q7solyqu

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 ibMOV r/m8, imm8C7 /0 iwMOV 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,机器码将是
c7     04       00 00 
         ^      ^        ^
       opcode  ModR/M   imm16 immediate operand

目的操作数[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

b8          00 00
    ^          ^
  Opcode       imm16 immediate source

AX目标由前导字节的低3位指定。您可以将其视为8个不同的操作码字节,每个寄存器一个,并具有隐式目标。这种解释(对这条不同指令的解释,而不是作业中不可能的解释)与教师对操作码“mov-to-AX”的描述基本相符。

但实际上,您可能会说mov ax, imm16是操作码,填充占位符的实际值是0操作数。

  • 8B /rmov r16, r/m16(例如:一个月三个月一个月)
  • 89 /rmov r/m16, r16(例如:一米三六英寸)
  • A1mov ax, moffs(例如mov ax, [1234h])。具有绝对偏移量和AL或AX目标的特殊情况no-ModRM短格式。
  • 第四个通常不会用于寄存器目的地,因为它更长:C7 /0 iwmov r/m16, imm16(例如,mov ax, 0的更长编码)。
  • 也称为8C /r mov r/m16, Sreg(例如mov ax, ds)。
  • 现代的x86有更多的形式,如mov r/m16, cr0..7(386中的新形式)和mov r/m16, dr0..7(386),但控制寄存器直到286 smsw(存储机器状态字)才存在(?)。

或者,您可以按照英特尔手册中的说明来理解它,B8+ rwiwMOV 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 *)

相关问题