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バージョンを機能させることができません。
何か案は?
---編集----
スティーブンキヤノンの答えは、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)
これは、私が達成しようとしていたことを示しています。lea0x10(%rip)、%rsiは、lea命令の17バイト後にアドレス0x400096をロードします。このアドレスは、Hello world文字列を見つけることができるため、位置に依存しないコードになります。
文字列のaddressを%rsi
にロードしたいと思います。コードは、アドレス自体ではなく、そのアドレスからクアッドワードを読み込もうとします。あなたが欲しい:
lea msg(%rip), %rsi
私が間違っていなければ。ただし、テストするLinuxボックスはありません。
%rsiのmsgのaddressが必要なので、次を置き換えるだけです。
mov msg(%rip),%rsi
と:
lea msg(%rip),%rsi