Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
549 views
in Technique[技术] by (71.8m points)

linux - Determining when NASM can infer the size of the mov operation

Something has got me confused in x86 assembly for a while, it's how/when can NASM infer the size of the operation, here's an example:

mov ebx, [eax]

Here we are moving the 4 bytes stored at the address held in eax into ebx. The size of the operation is inferred as 4 bytes because the register is 32 bits.

However, this operation doesn't get inferred and throws a compile error:

mov [eax], 123456

Of course the solution is this:

mov dword [eax], 123456

Which will move the 32 representation of the number 123456 into the bytes stored at the address held at eax.

But this confuses me, surely it can see eax is 32 bit, so shouldn't it assume I want to store it as a 32 bit value without me having to specify dword after the mov?

Surely if I wanted to put the 16 bit representation of 12345 (smaller number to fit in 16 bits) into eax I would do this:

mov ax, 12345
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The operand-size would be ambiguous (and so must be specified) for any instruction with a memory destination and an immediate source. (Neither operand actually being a register, even if using one or more in an addressing mode.)

Address-size and operand-size are separate attributes of an instruction.


Quoting what you said in a comment on another answer, since I think this gets at the core of your confusion:

I would expect mov [eax], 1 to set the 4 bytes held in memory address eax to the 32 bit representation of 1

The BYTE/WORD/DWORD [PTR] annotation is not about the size of the memory address; it's about the size of the variable in memory at that address. Assuming flat 32-bit addressing, addresses are always four bytes long, and therefore must go in Exx registers. So, when the source operand is an immediate value, the dword (or whatever) annotation on the destination operand is the only way the assembler can know whether it's supposed to modify 1, 2, or 4 bytes of RAM.

Perhaps it will help if I demonstrate the effect of these annotations on machine code:

$ objdump -d -Mintel test.o
...
   0:      c6 00  01             mov    BYTE PTR  [eax], 0x1
   3:   66 c7 00  01 00          mov    WORD PTR  [eax], 0x1
   8:      c7 00  01 00 00 00    mov    DWORD PTR [eax], 0x1

(I've adjusted the spacing a bit compared to how objdump actually prints it.)

Take note of two things: (1) the three different operand prefixes produce three different machine instructions, and (2) using a different prefix changes the length of the source operand as emitted into the machine code.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...