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

发布于 2024-09-10 02:21:44 字数 2019 浏览 7 评论 0原文

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

例如,以下 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 版本正在运行。

有什么想法吗?

--- 编辑 ----

Stephen Canon 的回答使 RIP 版本有效。

现在,当我反汇编 RIP 版本的可执行文件时,我得到:

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)

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

撧情箌佬 2024-09-17 02:21:44

我相信您想将字符串的地址加载到%rsi中;您的代码尝试从该地址而不是地址本身加载四字。你想要:

lea msg(%rip), %rsi

如果我没记错的话。不过,我没有可供测试的 Linux 机器。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文