Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use RIP Relative Addressing in a 64-bit assembly program?

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.

like image 215
Erik Avatar asked Jul 14 '10 20:07

Erik


People also ask

How does RIP relative addressing work?

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.

What is the rip register?

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.


1 Answers

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.

like image 180
Stephen Canon Avatar answered Sep 17 '22 20:09

Stephen Canon