.data
num1 word 0FEEDh
.code
main PROC
mov ecx, 0E4C7FFFDh ;ecx = 0E4C7FFFD hex
sub ecx, num1 ;;;;; error on this line
I want to be able to subtract the variable num1 from the register ecx, but that attempt gives:
error A2022: instruction operands must be the same size
I am very new to Assembly and am trying to figure out the basics. How can I go about doing this?
CodePudding user response:
ecx is a 32-bit register, a dword (double-word); in x86 terminology, a WORD is 2 bytes.
When you tried:
sub ecx, num1 ;ecx = ecx - num1
The assembler checked label num1 and found it to be of type word, and so tried to generate
sub ecx, word ptr [num1] ;ecx = ecx - num1
but that opcode doesn't exist.
A sub r32, r/m32 form of sub does exist, but loading 4 bytes from a 2-byte variable will pull in 2 bytes of garbage in the high half.
sub ecx, dword ptr [num1] ; don't *just* change to this
That would assemble, but you'd need to change num1 to a dword for it to be correct. (Unless you wanted to also read whatever 2 bytes you assembled after num1 into your .data section). And if you use num1 dword 0FEEDh, MASM sub ecx, num1 will work because it will infer the right size for the memory operand. If you want to let MASM check your variable sizes against the way you use them, leave out operand-size overrides unless you need them (e.g. to copy 4 bytes at once from a string.)
The assembler recommends fixing the problem by making num1 a dword variable or by changing ecx to cx. It's not wrong (cx can't store your constant but masm doesn't know that); however there is one other possibility. You can zero-extend to a scratch register and subtract that:
movzx edx, num1 ; zero-extending load from a byte or word var
sub ecx, edx
Or if num1 is signed (masm has an SWORD but I usually see WORD used for both signed and unsigned):
movsx edx, num1 ; sign-extending load
sub ecx, edx
