2010-07-14 3 views
21

AMD64 아키텍처의 Linux 어셈블리 프로그램에서 RIP 상대 주소 지정은 어떻게 사용합니까? AMD64 RIP 상대 주소 지정 모드를 사용하는 간단한 예제 (Hello World 프로그램)를 찾고 있습니다.64 비트 어셈블리 프로그램에서 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" 

를 I는 상대 주소 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 안녕하세요 내가 달성하기 위해 노력했다 보여줍니다

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) 

: 레아은 0x10 (% 립), % RSI를 Hello World 문자열을 찾을 수있는 주소 0x400096 인 lea 명령 다음에 17 바이트의 주소를로드하므로 위치 독립 코드가 생성됩니다.

+1

왜 17 바이트 (0x10은 16)입니까? – fadedbee

+3

https://www.tortall.net/projects/yasm/manual/html/nasm-effaddr.html :'RIP는 현재 명령어 바로 다음 위치의 주소를 포함하는 명령어 포인터 레지스터이지만' lea' 명령은 길이가 7 바이트가 아니라 1 바이트입니다. – fadedbee

+0

왜 '밀기'대신에'밀기'/'팝'한 쌍이 필요한가요? –

답변

18

주소%rsi에로드하고 싶습니다. 코드가 주소 자체가 아닌 해당 주소에서 쿼드 워드를로드하려고 시도합니다. 원하는 항목 :

lea msg(%rip), %rsi 

내가 실수하지 않은 경우. 그러나 나는 리눅스 박스를 테스트 할 필요가 없다.

+0

네, 그 작품, 고마워요! – Erik

+0

@ 에릭 : 기꺼이 도와 드리겠습니다. –

+4

lea msg (% rsp), % rsi (% rip), % rsi (또는 임의의 레지스터이지만 rip이 아닌)를 사용하는 경우 mes 레이블의 주소 자체가 현재 제공된 레지스터 값의 오프셋이 아니라 추가됩니다. 예를 들어 msg가 주소 0x1FF에 있고 lea msg (% rsp)를 사용하는 경우 % rsi는 disassembler가 0x10 (% rip)을 부여한 것처럼 rsi = * (rsp + 0x1FF)가 아닌 rsi = * ((rsp - 0x1FF) + rsp) 현재 rip으로부터의 거리와 msg는 0x10 byts입니다. 하지만 문서에서 립과 다른 레지스터 간의 계산에 차이가 있음을 발견 할 수 없습니다. – user2808671

관련 문제