64 비트 어셈블리 프로그램에서 RIP 상대 주소 지정을 사용하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/3250277

문제

AMD64 Archtitecture 용 Linux 어셈블리 프로그램에서 RIP 상대 주소 지정은 어떻게 사용합니까? 나는 AMD64 RIP 상대 상대를 사용하는 간단한 예 (안녕 세계 프로그램)를 찾고 있습니다.

예를 들어 다음 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 버전의 실행 파일을 분해 할 때 i가

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는 Hello World String을 찾을 수있는 LEA 명령이있는 LEA 명령 후 주소 17 바이트를로드하고 따라서 위치 독립적 인 코드가 생성됩니다.

도움이 되었습니까?

해결책

문자열의 주소 %rsi에로드하려는 것이 좋습니다.코드는 주소 자체가 아닌 해당 주소에서 쿼드 워드를로드하려고 시도합니다.원하는 :

lea msg(%rip), %rsi
. 내가 착각하지 않으면

.그러나 나는 테스트 할 리눅스 박스가 없다.

다른 팁

% rsi의 msg의 주소 이 필요하기 때문에 바로 대체하십시오 :

mov msg(%rip),%rsi
.

다음과 같이 :

lea msg(%rip),%rsi
.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top