-1

I know that both adr and ldr pseudo instructions loads addr of a label. The difference between them is that ldr is absolute but adr is PC-relative.

But when should I use which?

I always use ldr to get the address when writing a bare-metal assembly progress. Can you give an explanation and example of using the adr instruction? Is it related to PIC(Position-Independent-Code)?

wangloo
  • 27
  • 7
  • Another: [adrp and adrl in ARM Assembler](https://stackoverflow.com/questions/41906688/what-are-the-semantics-of-adrp-and-adrl-instructions-in-arm-assembly) – artless noise Sep 26 '22 at 18:30

1 Answers1

1

adr generates a PC-relative address. It takes the address of the instruction itself and adds a signed offset that is encoded in the instruction to it.

The ldr pseudo-instruction (that is, ldr x0, =label) loads a pre-generated absolute address from a PC-relative position. At compile time, the absolute address of label is generated and embedded somewhere in the binary, and the (actual PC-relative) ldr instruction then loads that value from that place.

If we take a sample program (_main because I'm on macOS):

.globl _main
.p2align 2
_main:
    adr x1, label
    ldr x2, =label
    mov w0, 0
    ret

label:
    mov w0, 0x1234
    ret

Compiling this and looking at it in a disassembler yields:

;-- _main:
0x100003f98      81000010       adr x1, sym.func.100003fa8
0x100003f9c      a2000058       ldr x2, 0x100003fb0
0x100003fa0      00008052       mov w0, 0
0x100003fa4      c0035fd6       ret
;-- func.100003fa8:
0x100003fa8      80468252       mov w0, 0x1234
0x100003fac      c0035fd6       ret
0x100003fb0      a83f0000       invalid
0x100003fb4      01000000       invalid

Thus, the above program is equivalent to:

.globl _main
.p2align 2
_main:
    adr x1, label
    ldr x2, addressof_label
    mov w0, 0
    ret

label:
    mov w0, 0x1234
    ret

.p2align 3
addressof_label:
    .8byte label

This adds one level of indirection, and means that in an environment with ASLR, the dynamic linker must add the ASLR slide to addressof_label.

Siguza
  • 21,155
  • 6
  • 52
  • 89