从寄存器中减去一个变量?错误 A2022:指令操作数的大小必须相同

Subtract a variable from a register? error A2022: instruction operands must be the same size

.data
    num1    word   0FEEDh

.code
main PROC
    mov     ecx, 0E4C7FFFDh   ;ecx = 0E4C7FFFD hex
    sub     ecx, num1         ;;;;; error on this line

我希望能够从寄存器 ecx 中减去变量 num1,但该尝试给出:

error A2022: instruction operands must be the same size

我是 Assembly 的新手,正在尝试了解基础知识。我该怎么做呢?

ecx是一个32位的寄存器,一个dword(double-word);在 x86 术语中,一个 WORD 是 2 个字节。
当您尝试时:

sub     ecx, num1         ;ecx = ecx - num1

assembler 检查标签 num1 并发现它是 word 类型,因此尝试生成

sub     ecx, word ptr [num1]    ;ecx = ecx - num1

但该操作码不存在。

确实存在 subsub r32, r/m32 形式,但是从一个 2 字节变量加载 4 个字节将在高半部分引入 2 个字节的垃圾。

sub     ecx, dword ptr [num1]   ; don't *just* change to this

那会 assemble,但您需要将 num1 更改为双字才能使其正确。 (除非您还想将 num1 之后 assembled 的任何 2 个字节读入您的 .data 部分)。如果您使用 num1 dword 0FEEDh,MASM sub ecx, num1 将起作用,因为它将推断内存操作数的正确大小。如果你想让 MASM 根据你使用它们的方式检查你的变量大小,请省略 operand-size 覆盖,除非你需要它们(例如一次从字符串中复制 4 个字节。)


assembler 建议通过将 num1 设为双字变量或将 ecx 更改为 cx 来解决此问题。没错(cx 不能存储你的常量,但 masm 不知道);但是还有另一种可能性。您可以 zero-extend 到临时寄存器并减去:

movzx   edx, num1    ; zero-extending load from a byte or word var
sub     ecx, edx

或者如果 num1 是有符号的(masm 有一个 SWORD 但我通常看到 WORD 用于有符号和无符号):

movsx   edx, num1    ; sign-extending load
sub     ecx, edx