2011-05-29 10 views
7

मैं मशीन कोड बनाने में एक असेंबलर के उपयोग का एक संक्षिप्त विवरण ढूंढ रहा हूं।एक असेंबलर कैसे काम करता है?

तो मुझे पता है कि असेंबली मशीन कोड का 1: 1 अनुवाद है। लेकिन मैं ऑब्जेक्ट कोड और लिंकर्स के बारे में भ्रमित हो रहा हूं और वे इसमें कैसे स्थानांतरित होते हैं।

मैं एक जटिल जवाब की जरूरत नहीं सिर्फ एक सरल एक वस्तु फाइलों में ठीक

+3

वास्तव में आवश्यक नहीं 1: 1 –

उत्तर

11

दोनों एक कोडांतरक और एक संकलक का अनुवाद स्रोत फ़ाइलों करना होगा है।

ऑब्जेक्ट फ़ाइलें अंतिम निष्पादन योग्य आउटपुट (लिंकर द्वारा जेनरेट) से पहले एक मध्यवर्ती चरण प्रभावी ढंग से होती हैं।

लिंकर निर्दिष्ट ऑब्जेक्ट फ़ाइलें और पुस्तकालय (जो ऑब्जेक्ट फ़ाइलों के संकुल हैं) लेता है और स्थानांतरण (या 'फ़िक्सअप') रिकॉर्ड को हल करता है।

ये स्थानांतरण रिकॉर्ड तब किए जाते हैं जब संकलक/असेंबलर स्रोत कोड में उपयोग किए गए फ़ंक्शन या चर के पते को नहीं जानता है, और इसके नाम के लिए संदर्भ उत्पन्न करता है, जिसे लिंकर द्वारा हल किया जा सकता है।

उदाहरण के लिए, आप एक प्रोग्राम दो स्रोत फ़ाइलों में अलग स्क्रीन के लिए एक संदेश, प्रिंट करना चाहते हैं का कहना है, और आप उन्हें अलग से इकट्ठा और (लिनक्स x86-64 syscalls का उपयोग कर उदाहरण) उन्हें लिंक करना चाहते हैं -

main.asm:

bits 64 
section .text 
extern do_message 
global _start 
_start: 
    call do_message 
    mov rax, 1 
    int 0x80 

message.asm:

bits 64 
section .text 
global do_message 
do_message: 
    mov rdi, message 
    mov rcx, dword -1 
    xor rax, rax 
    repnz scasb 
    sub rdi, message 
    mov rax, 4 
    mov rbx, 1 
    mov rcx, message 
    mov rdx, rdi 
    int 0x80 
    ret 

section .data 
message: db "hello world",10,0 

आप इन इकट्ठा और main.asm (जैसे, objdump -d main.o) की वस्तु फ़ाइल उत्पादन को देखें, तो आप करेंगे नहीं tice the 'call do_message' का 00 00 00 00 का पता है - जो अमान्य है।

0000000000000000 <_start>: 
    0: e8 00 00 00 00   callq 5 <_start+0x5> 
    5: 48 c7 c0 01 00 00 00 mov $0x1,%rax 
    c: cd 80     int $0x80 

लेकिन, एक स्थान परिवर्तन रिकॉर्ड पते के 4 बाइट के लिए किया जाता है:

$ objdump -r main.o 
main.o:  file format elf64-x86-64 
RELOCATION RECORDS FOR [.text]: 
OFFSET   TYPE    VALUE 
0000000000000001 R_X86_64_PC32  do_message+0xfffffffffffffffc 
000000000000000d R_X86_64_32  .data 

ऑफसेट '1' और प्रकार 'R_X86_64_PC32' जो इस संदर्भ को हल करने लिंकर बताता है , और निर्दिष्ट पते को हल ऑफसेट में निर्दिष्ट ऑफसेट में डाल दें।

जब आप अंतिम कार्यक्रम को 'ld -o program main.o message.o' से जोड़ते हैं, तो स्थानान्तरण सभी हल हो जाते हैं, और यदि कुछ भी अनसुलझा नहीं है, तो आपको निष्पादन योग्य के साथ छोड़ दिया जाता है।

00000000004000f0 <_start>: 
    4000f0: e8 0b 00 00 00   callq 400100 <do_message> 
    4000f5: 48 c7 c0 01 00 00 00 mov $0x1,%rax 
    4000fc: cd 80     int $0x80 

relocations उसी तरह चर के साथ ही कार्यों के लिए उपयोग किया जाता है:

जब हम objdump -d 'निष्पादन योग्य है, हम हल हो गई पता देख सकते हैं। वही प्रक्रिया तब होती है जब आप अपने प्रोग्राम को कई बड़े पुस्तकालयों जैसे कि libc के साथ लिंक करते हैं - आप 'मुख्य' नामक फ़ंक्शन को परिभाषित करते हैं, जिसमें libc का बाहरी संदर्भ होता है - फिर libc आपके प्रोग्राम से पहले शुरू होता है, और आपके 'मुख्य' फ़ंक्शन को कॉल करता है जब आप निष्पादन योग्य चलाते हैं।

+0

एएसएम -> ऑब्जेक्ट -> लिंकिंग ... साफ थोड़ा उदाहरण। –

+0

क्या आप कृपया बता सकते हैं कि ऑब्जेक्ट फ़ाइल में ऑफ़सेट क्यों एक है, और इसकी गणना कैसे की जाती है? क्षमा करें अगर यह एक बेवकूफ सवाल है। – gavlaaaaaaaa

+1

@gavlaaaaaaa: main.o में do_message स्थानांतरण संदर्भ का ऑफसेट 1 है क्योंकि कोड 0 से शुरू होता है, और ऑफ़सेट 0 ओपोड 'e8' है जो निर्देश 'कॉलक' है, ऑफसेट 1 अगले 32 की शुरुआत है -बिट मान जो 'कॉलक' निर्देश के लिए ऑपरेंड है। – matja

1

सरल स्पष्टीकरण:

एक बार विधानसभा भाषा ऑब्जेक्ट कोड में इकट्ठे है, लिंकर आदेशों कंप्यूटर को समझते हैं और चला सकते हैं की एक निष्पादन में वस्तु कोड में परिवर्तित किया जाता है।जेनरेट किए गए मशीन कोड को सीपीयू के नियंत्रक द्वारा व्याख्या किया जा सकता है।

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