2010-07-14 11 views
21

एएमडी 64 आर्किटेक्चर के लिए लिनक्स असेंबली प्रोग्राम में आरआईपी रिलेटिव एड्रेसिंग का उपयोग कैसे करूं? मैं एक साधारण उदाहरण (एक हैलो वर्ल्ड प्रोग्राम) की तलाश में हूं जो एएमडी 64 आरआईपी सापेक्ष एड्रेसिंग मोड का उपयोग करता है।64-बिट असेंबली प्रोग्राम में आरआईपी रिलेटिव एड्रेसिंग का उपयोग कैसे करें?

उदाहरण के लिए निम्नलिखित 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" 

मैं अनुमान लगा रहा हूँ कि सापेक्ष आरआईपी को संबोधित करते का उपयोग कर एक ही कार्यक्रम होगा कुछ की तरह:

.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 

लेकिन मुझे आरआईपी संस्करण काम नहीं मिल रहा है।

कोई विचार?

--- संपादित ----

स्टीफन कैनन का जवाब आरआईपी संस्करण काम में आता है।

अब जब मैं आरआईपी संस्करण के निष्पादन योग्य एकत्रित न मैं:

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 (% RIP),% RSI पता 0x400096 पता है कि लीए निर्देश के बाद पता 17 बाइट्स लोड करता है जहां हैलो वर्ल्ड स्ट्रिंग मिल सकती है और इस प्रकार स्थिति स्वतंत्र कोड हो सकती है।

+1

क्यों 17 बाइट्स (0x10 16 है)? – fadedbee

+3

https://www.tortall.net/projects/yasm/manual/html/nasm-effaddr.html कहता है: 'आरआईपी निर्देश सूचक रजिस्टर है, जिसमें वर्तमान निर्देश के तुरंत बाद स्थान का पता शामिल है' लेकिन ' लीए निर्देश सात बाइट लंबा है, एक नहीं। – fadedbee

+0

'mov' के बजाय' push'/'pop' जोड़े क्यों? –

उत्तर

18

मेरा मानना ​​है कि आप पता अपनी स्ट्रिंग के %rsi में लोड करना चाहते हैं; आपका कोड पते के बजाए उस पते से एक प्रश्नोत्तरी लोड करने का प्रयास करता है। आप चाहते हैं:

lea msg(%rip), %rsi 

यदि मुझे गलत नहीं है। हालांकि, मेरे पास परीक्षण करने के लिए लिनक्स बॉक्स नहीं है।

+0

हाँ, यह काम करता है, बहुत बहुत धन्यवाद! – Erik

+0

@Erik: मदद करने में खुशी हुई। –

+4

यदि lea msg (% rsp),% rsi (% rip) के बजाय% rsi,% rsi (या कोई रजिस्टर लेकिन चिपका नहीं है) का उपयोग करते हुए एमएस लेबल के पते को वर्तमान प्रदत्त रजिस्टर मान से ऑफ़सेट नहीं जोड़ा जाता है। उदाहरण के लिए यदि संदेश 0x1FF में है तो lea msg (% rsp) का उपयोग करते हुए,% rsi rsi = * (rsp + 0x1FF) rsi = * ((rsp - 0x1FF) + rsp) का कारण बनता है क्योंकि डिस्सेबलर ने 0x10 (% rip) दिया है क्योंकि वर्तमान चीर से दूरी और संदेश 0x10 बाइट्स है। लेकिन मुझे दस्तावेज़ों में नहीं मिल रहा है कि चीर और अन्य रजिस्टरों के बीच गणना में अंतर है – user2808671

संबंधित मुद्दे