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

26,347

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.

Share:
26,347
Erik
Author by

Erik

I like programming in Ruby on Linux machines.

Updated on February 16, 2020

Comments

  • Erik
    Erik about 4 years

    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.