Difference between (sp) and [sp] in assembly
Asked Answered
S

1

1

I was experimenting with the NASM assembler, when I came across a problem:

mov (sp),bx
mov [sp],bx

The first instruction is assembled properly while the second one is not, and gives me the error:

error: invalid effective address

Why is this? What's the difference between the two?

Sandler answered 7/1, 2020 at 13:49 Comment(3)
[] means memory reference, () are just normal arithmetic parentheses which nasm allows for whatever reason. As such your first instruction is just mov sp, bx which is valid, but [sp] is not because 16 bit mode does not support that form of effective address.Galbraith
assembly language is defined by the assembler the tool not the target (x86) nor style (AT&T vs intel), the assembler defines the language and certainly with x86 over time nuances specific to indirect addressing have evolved/changed, lots of mips educated folks are forcing mips assembler style/habits onto other targets as they develop new tools for those targets. so its a mismash of syntax and is very tool specific so you can will see (blah) or [blah] mean indirect addressing depending on the tool and its implemented assembly language.Outlander
some specific version of nasm being a specific tool has a specific language or set of language options that you must conform to, it is a nasm thing not an x86/intel/AT&T thing. have to read the manual or in the case of nasm possibly the source code to find out all the nuances and options.Outlander
S
4

(%sp) would be an AT&T syntax addressing mode. (Invalid because 16-bit addressing modes can't use SP directly, only BP|BX + SI|DI NASM x86 16-bit addressing modes; that's also the reason mov [sp], bx is invalid.)

In NASM syntax, square brackets [] mean a memory operand.


In NASM, the parens () around SP are removed just like any compile-time expression,
so mov (sp), bx assembles to 89DC mov sp,bx. Try it yourself by assembling and using ndisasm on the output. (Or assemble into -felf32 and use objdump)

This is a mov between two registers, overwriting the stack pointer. Very likely not what you want, and totally different from storing to memory with mov [bp], bx or whatever.

In NASM, you might use parens when writing something like mov ax, (1+3) * 4 so NASM's expression parser handles parens, and apparently having a register name inside parens doesn't change anything.

I only mentioned AT&T syntax at the top of this answer because that and Plan9/Go syntax are the only time you'd normally put a register name inside parens; it's just confusing in NASM syntax; don't do it.

Shroud answered 7/1, 2020 at 14:9 Comment(4)
So does 32 bit mode allow something like mov ebx,[esp] or mov [esp],ebx?Sandler
@SuraajKS: yes. Referencing the contents of a memory location. (x86 addressing modes). That would be a load, not a store. (That's also allowed in 16-bit mode (on a 386 or higher), and could be useful if you know SP is zero-extended into ESP, if you don't want to set up BP as a frame pointer). Segment limits still apply.)Shroud
Segment limits meaning? As set up by the descriptor tables (GDT)??Sandler
@SuraajKS Segment size in x86 real mode explains that using 32-bit addressing modes doesn't bypass the 64k segment limit. Real mode doesn't have a GDT, but yes in 16-bit protected mode, or after switching back to real mode from protected mode, the segment limit loaded from the GDT by mov ss, something still applies.Shroud

© 2022 - 2024 — McMap. All rights reserved.