Search code examples
assemblyarmlpc

Difference between Rx and [Rx]


LDR R0, R1    ; statement 1
LDR R0, [R1]  ; statement 2

What is the difference between two statements?

In statement 1, is the address of register stored in R0?

In statement 2, is the 4 bytes of data pointed by R1 loaded into R0?


Solution

  • Yes, ldr r0, [r1] loads 4 bytes from memory, using R1 as the address.

    The 2nd operand of ldr has to be memory, using some addressing mode1, not a bare register.

    LDR R0, R1 is either a syntax error, or tries to use R1 as a symbol name (like any other string like ldr r0, foo), not a register. If you'd bothered to try it, you'd see an error message like Error: internal_relocation (type: OFFSET_IMM) not fixed up (from GNU as). This is the same error message you get for ldr r0, foo, when your source file doesn't contain that label.

    (If you did have an R1: label somewhere in your source, this ldr R0, R1 load would reference it. Disassembling again, you'd get ldr r0, [pc, #4] if that label is after 2 more instructions. Again, exactly the same as if you used foo instead of R1 as the symbol name. Using register names as symbols is a bad idea for human readability, but that's what happens if you actually do this with the GNU assembler (from GNU binutils). How does the LDR instruction load constants into registers? shows an example)

    If you want to copy registers, use mov r0, r1, a different mnemonic (and machine-code opcode) from ldr.


    Footnote 1: Or there's a pseudo-instruction form of ldr, like ldr r0, =0x1234 to put a constant into a register with the assembler's choice of instructions, or in some assemblers always a PC-relative load from a nearby "literal pool". But that kind of ldr in the asm source either assembles to ldr r0, [pc, #offset] or to some instruction(s) that aren't ldr at all. What does an equals sign = on the right side of a LDR instruction in ARM mean?