How do I use RIP Relative Addressing in a Linux assembly program for the AMD64 archtitecture? I am looking for a simple example (a Hello world program) that uses the AMD64 RIP relative adressing mode.
For example the following 64-bit assembly program would work with normal (absolute addressing):
.text .global _start _start: mov $0xd, %rdx mov $msg, %rsi pushq $0x1 pop %rax mov %rax, %rdi syscall xor %rdi, %rdi pushq $0x3c pop %rax syscall .data msg: .ascii "Hello world!\n"
I am guessing that the same program using RIP Relative Addressing would be something like:
.text .global _start _start: mov $0xd, %rdx mov msg(%rip), %rsi pushq $0x1 pop %rax mov %rax, %rdi syscall xor %rdi, %rdi pushq $0x3c pop %rax syscall msg: .ascii "Hello world!\n"
The normal version runs fine when compiled with:
as -o hello.o hello.s && ld -s -o hello hello.o && ./hello
But I can't get the RIP version working.
Any ideas?
--- edit ----
Stephen Canon's answer makes the RIP version work.
Now when I disassemble the executable of the RIP version I get:
objdump -d hello
0000000000400078 <.text>: 400078: 48 c7 c2 0d 00 00 00 mov $0xd,%rdx 40007f: 48 8d 35 10 00 00 00 lea 0x10(%rip),%rsi # 0x400096 400086: 6a 01 pushq $0x1 400088: 58 pop %rax 400089: 48 89 c7 mov %rax,%rdi 40008c: 0f 05 syscall 40008e: 48 31 ff xor %rdi,%rdi 400091: 6a 3c pushq $0x3c 400093: 58 pop %rax 400094: 0f 05 syscall 400096: 48 rex.W 400097: 65 gs 400098: 6c insb (%dx),%es:(%rdi) 400099: 6c insb (%dx),%es:(%rdi) 40009a: 6f outsl %ds:(%rsi),(%dx) 40009b: 20 77 6f and %dh,0x6f(%rdi) 40009e: 72 6c jb 0x40010c 4000a0: 64 21 0a and %ecx,%fs:(%rdx)
Which shows what I was trying to accomplish: lea 0x10(%rip),%rsi loads the address 17 bytes after the lea instruction which is address 0x400096 where the Hello world string can be found and thus resulting in position independent code.
RIP -relative addressing is a new form of effective addressing introduced with 64-bit long mode. The point is that it makes it easier to write position-independent code because you can make any memory reference RIP -relative. In fact, RIP -relative addressing is the default addressing mode in 64-bit applications.
The %rip register on x86-64 is a special-purpose register that always holds the memory address of the next instruction to execute in the program's code segment.
I believe that you want to load the address of your string into %rsi
; your code attempts to load a quadword from that address rather than the address itself. You want:
lea msg(%rip), %rsi
if I'm not mistaken. I don't have a linux box to test on, however.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With