Why in NASM do we have to use square brackets ([ ]) to MOV to memory location?

4

For example if I have a variable named test declared like:

test db 0x01      ;suppose the address is 0x00000052

If I do something like:

mov rax, test     ;rax = 0x00000052
mov rax, [test]   ;rax = 0x01

But, when I try to save in it, if we're following the same pattern:

mov test, 0x01    ;address 0x00000052 = 0x01
mov [test], 0x01  ;address 0x01 = 0x01

But it actually is:

mov [test], 0x01  ;address 0x00000052 = 0x01

So, why the square brackets behave differently depending if they are the first or second operands?

assembly
nasm
yasm
asked on Stack Overflow Mar 28, 2018 by Pedro Palhari

2 Answers

5

In most assemblers, using square brackets dereferences a memory location. You are treating the value as a memory address.

For example, let's take this for an example.

mov ax, [0x1000]

This will get the value at 0x1000 and put it into AX. If you remove the square brackets, you only move 0x1000.

If you move a value to a number, you are putting it into the value (memory location).

If you are a C developer, here's an example problem.

Don't let this example annoy you if you've been bullied into learning C by others, calling you a 'troll'.

You can ignore this if you want but you might have known about scanf() if you know C.

int a = 10;
scanf("%d", a);

Now, this is a very common mistake because we are not getting the memory address of the variable. Instead, we are using its value as the address. The scanf() function requires you to give the the address.

If we did this,

scanf("%d", &a);

we would have the address of the variable a.

answered on Stack Overflow Mar 28, 2018 by Steve Woods • edited Jun 20, 2020 by Community
1

Steve Woods' post gave me the impression he thinks & is a dereference operator. & is C's reference operator. * is C's dereference operator. The OP has a valid concern. [] can seem to function as both depending on the context. It is neither a dereference or reference operator. It is the "This is a memory address!!!" operator.

https://nasm.us/doc/nasmdoc3.html#section-3.3

An effective address is any operand to an instruction which references memory. Effective addresses, in NASM, have a very simple syntax: they consist of an expression evaluating to the desired address, enclosed in square brackets.

; assume wordvar was used as a label, and the linker gave it address 6291668
; or mostly equivalently, you used   wordvar equ 6291668

mov eax,wordvar         ; eax = 6291668. Move value 6291668 to eax.
mov eax,[wordvar]       ; eax =  12. Move contents of address 6291668 to eax.

mov eax,13
; mov wordvar,eax       ; Move eax to value 6291668. syntax error.
mov [wordvar],eax       ; mem(6291668) = 13. Move eax to address 6291668.

When an operand is a memory address, it has to be enclosed in square brackets to tell nasm that is the case. It's not dereferencing it, it's just letting nasm know what's up. If it was equivalent to the dereference operator,

mov [wordvar], eax

would set memory location 12 to 13.

It's not the dereference operator. It's the "this is a memory address" operator. This appears to be both dereferencing and referencing in different cases because x86 and x86_64 instructions behave differently based on whether its operands are memory locations or values. I am teaching myself assembly and I had to explain this to figure it out myself.

answered on Stack Overflow Feb 9, 2019 by Justin • edited Feb 9, 2019 by Peter Cordes

User contributions licensed under CC BY-SA 3.0