本文将介绍x64 RIP-relative addressing的使用方法。

1. Introduction

RIP-relative addressing: this is new for x64 and allows accessing data tables and such in the code relative to the current instruction pointer, making position independent code easier to implement.

position independent code的相关内容较为复杂,本文不会介绍,后续会推出系列文章介绍该部分内容。

2. Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# ----------------------------------------------------------------------------------------
# Writes "Hello, World" to the console using only system calls. Runs on 64-bit Linux only.
# To assemble and run:
#
# gcc -c hello.s && ld hello.o && ./a.out
#
# or
#
# gcc -nostdlib hello.s && ./a.out
# ----------------------------------------------------------------------------------------

.global _start

.text
_start:
# write(1, message, 13)
mov $1, %rax # system call 1 is write
mov $1, %rdi # file handle 1 is stdout
lea message(%rip), %rsi # address of string to output
mov $13, %rdx # number of bytes
syscall # invoke operating system to do the write

# exit(0)
mov $60, %rax # system call 60 is exit
xor %rdi, %rdi # we want return code 0
syscall # invoke operating system to exit
message:
.ascii "Hello, world\n"

lea message(%rip), %rsi就使用了x64 RIP-relative addressing。

AT&T: ‘symbol(%rip)’, Intel: ‘[rip + symbol]’
Points to the symbol in RIP relative way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
acrn@acrn:~/test$ objdump -D a.out

a.out: file format elf64-x86-64


Disassembly of section .text:

0000000000400078 <_start>:
400078: 48 c7 c0 01 00 00 00 mov $0x1,%rax
40007f: 48 c7 c7 01 00 00 00 mov $0x1,%rdi
400086: 48 8d 35 15 00 00 00 lea 0x15(%rip),%rsi # 4000a2 <message>
40008d: 48 c7 c2 0d 00 00 00 mov $0xd,%rdx
400094: 0f 05 syscall
400096: 48 c7 c0 3c 00 00 00 mov $0x3c,%rax
40009d: 48 31 ff xor %rdi,%rdi
4000a0: 0f 05 syscall

00000000004000a2 <message>:
4000a2: 48 rex.W
4000a3: 65 6c gs insb (%dx),%es:(%rdi)
4000a5: 6c insb (%dx),%es:(%rdi)
4000a6: 6f outsl %ds:(%rsi),(%dx)
4000a7: 2c 20 sub $0x20,%al
4000a9: 77 6f ja 40011a <message+0x78>
4000ab: 72 6c jb 400119 <message+0x77>
4000ad: 64 fs
4000ae: 0a .byte 0xa

第11行展示了x64 RIP-relative addressing的效果。为什么是0x15呢?计算公式为:0x4000a2 - 0x40008d

3. Extension

Intel SDM Vol2 2.2.1.6 RIP-Relative Addressing

A new addressing form, RIP-relative (relative instruction-pointer) addressing, is implemented in 64-bit mode. An effective address is formed by adding displacement to the 64-bit RIP of the next instruction.

想了解更多细节的话,请查阅SDM。


参考资料:

  1. Memory References
  2. Introduction to x64 Assembly
  3. How to use RIP Relative Addressing in a 64-bit assembly program?
  4. x64下PIC的新寻址方式:RIP相对寻址