代码之家  ›  专栏  ›  技术社区  ›  Erik

如何在64位汇编程序中使用RIP相对寻址?

  •  25
  • Erik  · 技术社区  · 14 年前

    如何在AMD64架构的Linux汇编程序中使用RIP相对寻址? 我正在寻找一个简单的例子(HelloWorld程序),它使用AMD64RIP相对寻址模式。

    例如,以下64位汇编程序可以正常工作(绝对寻址):

    .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"
    

    我猜使用RIP相对寻址的同一个程序应该是:

    .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"
    

    当使用以下方法编译时,正常版本运行良好:

    as -o hello.o hello.s && ld -s -o hello hello.o && ./hello
    

    但我不能让翻录版工作。

    有什么想法吗?

    ---编辑----

    史蒂芬·卡农的回答使翻录版起作用。

    现在,当我分解rip版本的可执行文件时,我得到:

    objdump-d你好

    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)
    

    这显示了我试图完成的任务:lea 0x10(%rip),%rsi在lea指令后加载地址17字节,地址为0x400096,在这里可以找到hello world字符串,从而产生位置无关的代码。

    1 回复  |  直到 9 年前
        1
  •  22
  •   Stephen Canon    14 年前

    我相信你想加载 地址 把你的绳子 %rsi ;您的代码尝试从该地址而不是地址本身加载四字。你想要:

    lea msg(%rip), %rsi
    

    如果我没弄错的话。不过,我没有一个Linux设备可供测试。