问题
I have a little problem understanding PTR Operator, I can easily move large memory into small register example below:
ax = small register which is 2 byte
memory = variable which is 4 byte
.data
variable dword 05010h
.code
mov ax,WORD PTR variable
It will works fine.
Now my problem is I don't understand why I can't move large register like eax into a small memory variable which is 2 byte?
Example:
.data
variable word ?
.code
mov eax, 01050h
mov variable, word ptr eax
It's says: Error invalid use of register
Note: it works fine if the size is match
回答1:
The problem is that you are obviously not aware what the following instruction does:
mov ax, word ptr variable
This instruction does not read the 32-bit variable and write the variable to a 16-bit register!
But what does it do?
In general the CPU does not know which data type is stored in a certain memory location. Memory at the address variable may contain the following bytes:
01h 02h 03h 04h
This can be four 8-bit variables, two 16-bit variables (with the values 201h and 403h), one 32-bit variable with the value 4030201h or even one 16-bit and two 8-bit variables.
Because the CPU does not know which kind of variables is stored in the memory it is up to the programmer (or the compiler) to write an assembler program in a way that a 16-bit variable is accessed as 16-bit variable.
The instruction mov ax, variable means: "There is a 16-bit variable in the RAM at the location (address) variable. Read it and write it into the ax register."
The CPU will do this. Because the memory contains the bytes 01h 02h 03h 04h in our example it will read the two bytes 01h 02h and interpret them as 16-bit variable (having the value 201h).
Using so-called "little-endian" CPUs (like x86) this will result in the "correct" value when the 32-bit variable has a "small" value because the instruction will effectively read the low 16 bits of the 32-bit variable.
By the way: Using "big-endian" CPUs (like PowerPC) even this would not work any more because the high (and not the low) 16 bits of the 32-bit variable would be read.
Of course you could also read a memory location containing a 16-bit variable into a 32-bit register:
mov eax, variable
Let's say in the example above 01h 02h 03h 04h are two 16-bit variables having the values 201h and 403h. If you read this RAM memory as 32-bit value you'll get 4030201h as result, not 201h!
x86 CPUs (since the 80386) have two instructions movsx (sign-extend high bits) and movzx (set high bits to zero) which are used to copy a smaller value into a larger register.
These instructions allow you to "correctly" read a 16-bit value into a 32-bit register.
EDIT
According to Peter Cordes MASM explicitly requires a dword ptr in mov eax, dword ptr variable because MASM will otherwise check if variable is really 32-bit and print an error message.
For the CPU the instructions mov eax, variable and mov eax, dword ptr variable are however exactly the same instruction.
mov variable, word ptr eaxIt's says:
Error invalid use of register
The instruction would probably (I'm not sure as I don't use MASM) be named:
mov dword ptr variable, eax
However you should be aware what this instruction will do: It will overwrite 32 bits in memory: The variable and the data which is following variable in memory. I doubt that this is what you really want to do.
If you want to "convert" a 32-bit value into a 16-bit value like the following C code:
variable16 = (unsigned short)variable32;
... the following assembler code will do the job:
mov eax, variable32
mov variable16, ax
... because ax is the low 16 bits of eax.
来源:https://stackoverflow.com/questions/49218510/move-large-register-into-small-memory