2009-12-31 21 views
5

के काम से स्पष्ट नहीं है मैं विंडोज़ पर सी भाषा का उपयोग कर रहा हूं। यह प्रश्न पहले What happens to identifiers in a program? का हिस्सा था। मैंने इसे कम करने के लिए इसे तोड़ दिया। प्रश्नों का यह एक स्टैंडअलोन क्वेरी है (पिछले प्रश्न पर निर्भर नहीं है)लिंकर

यदि लिंक करने के लिए कुछ भी नहीं है (यानी मैं किसी भी पुस्तकालय का उपयोग नहीं कर रहा हूं। मुझे पता है कि यह किसी भी उपयोग का नहीं होगा।) लिंकर बदल जाएगा असेंबलर का ऑब्जेक्ट कोड आउटपुट? यदि ऐसा है तो यह क्या बदलता है?

मैंने सुना है कि LINKER कुछ स्मृति मैपिंग का संचालन भी करता है। मुझे समझ में नहीं आता कि कैसे। कार्यक्रम नहीं चल रहा है, यह सिर्फ विनिर्माण चरण में है। लिंकर मेमोरी को कैसे मैप कर सकता है? यह कैसा दिखता है? LINKER के सभी कार्य क्या हैं?

जब लोग "स्थानांतरण", "पता बाध्यकारी" का संदर्भ लेते हैं। मैं वास्तव में उनका मतलब क्या नहीं मिलता है। यह & क्या है इसका उद्देश्य क्या है?

कुछ डीबगर्स इस तरह की जानकारी दिखाते हैं: कॉल स्टैक: 0xfffef32, 0xf3234fe आदि .. यह रन टाइम सही है? या लिंकर के तथाकथित "मेमोरी मैपिंग" के मेमोरी पते हैं?

जब लोग symbols या symbol table जैसे कुछ को संदर्भित करते हैं। क्या उनका मतलब पहचानकर्ता (परिवर्तनीय नाम, निरंतर नाम, फ़ंक्शन नाम) हैं?

मैंने इंटरनेट पर जानकारी की खोज की लेकिन कुछ भी उपयोगी नहीं मिला। हो सकता है कि मुझे यकीन नहीं है कि क्या खोजना है। मैं इस पर बड़ी किताबें नहीं पढ़ना चाहता हूं। लेकिन अगर कोई लेख हैं, तो ट्यूटोरियल जो अवधारणाओं को स्पष्ट करते हैं। यह भी सहायक होगा।

मैं एक नौसिखिया प्रोग्रामर हूं। तो, यह बहुत अच्छा होगा कि आप सरल लेकिन तकनीकी शर्तों में समझा सकते हैं।

+0

आपके द्वारा उपयोग की जाने वाली भाषा और लिंकर निर्दिष्ट करना उपयोगी होगा। अलग-अलग लिंकर्स थोड़ा अलग काम कर सकते हैं। –

उत्तर

1

मैं इस चर्चा के लिए सी के साथ काम करूंगा।

सी प्रोग्राम के लिए यह दुर्लभ है कि कम से कम कुछ लाइब्रेरी फ़ंक्शंस का संदर्भ न दें; इसलिए यदि आपका कोड केवल एक मॉड्यूल (फ़ाइल) में है, तो आमतौर पर लाइब्रेरी फ़ंक्शंस के संदर्भ होंगे। आपके प्रोग्राम के संकलित रूप में, वे संदर्भ बाहरी संदर्भ तालिका में हैं, यानी एक सारणी जिसमें टेक्स्ट नाम आपके प्रोग्राम के उन स्थानों के साथ दिखाई देते हैं जो उन बाहरी पते को संदर्भित करना चाहते हैं।

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

भले ही आप किसी बाहरी मॉड्यूल का संदर्भ न दें, लिंक को शायद आपके कोड में कुछ सापेक्ष संदर्भों को पूर्ण रूप से परिवर्तित करने की आवश्यकता होगी; यानी एक बार यह "जानता है" जहां फ़ाइल में आपका कोड बैठे जा रहे हैं, यह चीजों को सही अंतिम पते असाइन कर सकता है।

4

जब आप किसी स्रोत फ़ाइल को संकलित करते हैं, तो इसे आमतौर पर संकलक/असेंबलर द्वारा कई अनुभागों में विभाजित किया जाता है। एक काल्पनिक उदाहरण के रूप में कल्पना करें कि निम्न अनुभागों उपयोग किया जाता है:

  • .text - निरंतर डेटा
  • .data शामिल हैं - -/लिखने प्रारंभ डेटा
  • पढ़ शामिल सभी निष्पादन योग्य कोड
  • .const शामिल ।बीएसएस - पढ़ने/लिखने शामिल अप्रारंभीकृत डेटा

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

उदाहरण के लिए:

int i; 
const j = 3; 
int k = 4; 
int l; 
int main() 
{ 
return 1; 
} 

यह निम्न प्रतीक तालिका में परिणाम सकता है:

Symbol Section Offset 
i  .bss 0 
j  .const 0 
k  .data 0 
l  .bss 4 
main .text 0 

वस्तु फ़ाइल में, प्रतीक तालिका के अलावा, प्रत्येक अनुभाग में डेटा रखा जा सकता है । इस उदाहरण में, .text खंड में "रिटर्न 1" के लिए ऑब्जेक्ट कोड होगा, कॉन्स्ट अनुभाग में 3 होगा, डेटा अनुभाग में 4 होगा। .bss अनुभाग को ऑब्जेक्ट फ़ाइल में होने की आवश्यकता नहीं होगी, क्योंकि चर शुरू नहीं किया गया है।

पहली बात यह है कि एक लिंकर इनपुट ऑब्जेक्ट फ़ाइल के सभी अनुभागों को जोड़ना और उसके अनुसार प्रतीक ऑफसेट को समायोजित करना है।

अब हम "स्थानांतरण" या "पता बाध्यकारी" कहलाते हैं। मान लें कि एक काल्पनिक प्रणाली में, निष्पादन योग्य कोड 0x1000 पते पर शुरू होता है। आइए यह भी कहें कि किसी प्रोग्राम के डेटा अनुभाग निष्पादन योग्य कोड के बाद भी पृष्ठ सीमा पर प्रारंभ करना चाहते हैं। लिंकर 0x1000 को concatenated .text अनुभागों के आधार के रूप में असाइन करेगा और सभी प्रतीकों को समायोजित करेगा। फिर .const, .data, और .bss अनुभागों का आधार समान रूप से स्मृति में उपयुक्त स्थानों में रखने के लिए।

कभी-कभी किसी सेक्शन में प्रतीकात्मक संदर्भ होते हैं। इन संदर्भों को संदर्भित प्रतीक की अंतिम स्थिति को दर्शाने के लिए लिंकर द्वारा अद्यतन किया जाना है। वस्तु फ़ाइल "स्थानांतरण रिकॉर्ड" उस तरह

section offset symbol 
.text 0x1234 foo 

लिंकर देखने के प्रत्येक अनुभाग में ऑफसेट प्रत्येक के लिए जाने के लिए और अंतिम प्रतीक मूल्य को प्रतिबिंबित करने के लिए वहाँ मूल्य अद्यतन करेगा हो सकता है।

यह सब करने के बाद, परिणामस्वरूप "पूर्ण" ऑब्जेक्ट फ़ाइल को स्मृति में (उचित स्थान पर, निश्चित रूप से) लोड किया जा सकता है और निष्पादित किया जा सकता है।

+0

धन्यवाद। वह बहुत मददगार था। लेकिन कार्यों के बारे में क्या? क्या उनके पास समान ऑफ़सेट हैं? उस मामले में ऑफसेट की गणना कैसे की जाएगी? जब इसे किसी चर को संदर्भित करने या फ़ंक्शन को कॉल करने की आवश्यकता होती है। इसे यह कैसे करना है? अगर मुझे 'l = k + 2' की आवश्यकता है तो hypotheticall कहते हैं। यह कैसे करता है – Alice

+0

मैं इस बारे में स्पष्ट नहीं हूं: 'मान लीजिए कि एक काल्पनिक प्रणाली में, निष्पादन योग्य कोड 0x1000 पते पर शुरू होता है।' निष्पादन योग्य कोड से आपका क्या मतलब है? .text खंड? एक और लाइब्रेरी ऑब्जेक्ट फ़ाइल का? 0x1000 ऑफ़सेट है? थोड़ा उलझन में - मुझे यह समझ में नहीं आया: 'चलिए यह भी कहते हैं कि किसी प्रोग्राम के डेटा अनुभाग निष्पादन योग्य कोड के बाद भी पृष्ठ सीमा पर शुरू करना चाहते हैं।' – Alice

+0

हां, मेरे उदाहरण में निष्पादन योग्य कोड .text अनुभाग में रहता है (रों)। वे जोड़ने के दौरान एक साथ संयोजित हैं। फ़ंक्शंस के लिए ऑफ़सेट किसी अन्य प्रतीक की तरह समायोजित किए जाते हैं। हालांकि ।पाठ ऑफ़सेट 0x1000 से शुरू हो सकता है, जब सभी .text खंड संयुक्त होते हैं, तो अंतिम आकार उस से बहुत बड़ा हो सकता है। यदि कोड में एल = के + 2 होता है, तो ऑपरेशन कोड करने वाले ऑब्जेक्ट कोड में अंतिम गणना वाले मानों के लिए एल और के समायोजित (स्थानांतरण स्थान की वजह से) के पते होते हैं। –

1

कोई जवाब नहीं, सिर्फ एक सुझाव: "Linkers and Loaders" खरीदें, इसे कुछ बार पढ़ें। यह आश्चर्यजनक रूप से सहायक है।

+1

एक बहुत अच्छी किताब - लेखक ने मूल पांडुलिपि अध्याय ऑनलाइन http://www.iecc.com/linker/ –

+0

"कुछ बार" पर उपलब्ध कराए हैं ?? हे भगवान! क्या यह मुश्किल है? – Alice

+1

@ एलिस लिंकर्स अवधारणात्मक रूप से काफी सरल हैं, लेकिन अभ्यास में काफी जटिल हैं। और किसी भी अच्छी किताब एक से अधिक बार पढ़ने लायक है। –

1

यदि लिंक करने के लिए कुछ भी नहीं है (यानी .. मैं किसी भी पुस्तकालय का उपयोग नहीं कर रहा हूं। मुझे पता है कि यह किसी भी उपयोग का नहीं होगा।) क्या लिंकर असेंबलर के ऑब्जेक्ट कोड आउटपुट को बदल देगा? यदि ऐसा है तो यह क्या बदलता है?

यह हमेशा कुछ प्रारंभिक कोड को लिंक करता है। आप इसे आज़मा सकते हैं, एक खाली प्रोग्राम लिख सकते हैं और इसे लिंक कर सकते हैं, और फिर इसे अलग करने के लिए objdump -d का उपयोग करें।

मैंने सुना है कि LINKER कुछ स्मृति मैपिंग का संचालन भी करता है। मुझे समझ में नहीं आता कि कैसे। कार्यक्रम नहीं चल रहा है, यह सिर्फ विनिर्माण चरण में है। लिंकर मेमोरी को कैसे मैप कर सकता है? यह कैसा दिखता है? LINKER के सभी कार्य क्या हैं?

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

जब लोग "स्थानांतरण", "पता बाध्यकारी" का संदर्भ लेते हैं। मैं वास्तव में उनका मतलब क्या नहीं मिलता है। यह & क्या है इसका उद्देश्य क्या है?

सामान्य रूप से बाध्यकारी का अर्थ किसी नाम को मूल्य देना है, इस मामले में किसी फ़ंक्शन या वैश्विक चर के प्रतीक के लिए एक पता।

स्थानांतरित करने के लिए, आप आम तौर पर एक से अधिक ऑब्जेक्ट फ़ाइल को एक साथ जोड़ते हैं, और प्रत्येक ऑब्जेक्ट फ़ाइल अपने पते को इसके आरंभ से संबंधित ऑफ़सेट के रूप में निर्दिष्ट करती है। जब आप उन्हें एक साथ रखते हैं तो प्रत्येक को अपना पता सीमा मिल जाती है, और लिंकर पता सीमा में ऑफ़सेट मैप करके प्रतीक के लिए पते की गणना करता है। इसे स्थानांतरण कहा जाता है।

कुछ डीबगर्स इस तरह की जानकारी दिखाते हैं: कॉल स्टैक: 0xfffef32, 0xf3234fe आदि .. यह रन टाइम सही है? या लिंकर के तथाकथित "मेमोरी मैपिंग" के मेमोरी पते हैं?

वह 0xfffef32 स्टैक पर एक सामान्य पता होगा, क्योंकि स्टैक आमतौर पर स्मृति के शीर्ष पर रखा जाता है और नीचे की ओर बढ़ता है। स्टैक का उपयोग वापसी पते, स्थानीय चर और वास्तविक फ़ंक्शन पैरामीटर के लिए किया जाता है। ये स्थानीय हैं और स्टैक पॉइंटर से संबंधित पते पर संग्रहीत हैं, इसलिए उन्हें आमतौर पर लिंकर द्वारा नियंत्रित नहीं किया जाता है, बल्कि संकलक पहले से ही ऑफसेट को उपयोग करने के लिए जानता है और उन्हें असेंबली कोड में रखता है।

जब लोग प्रतीकों या प्रतीक तालिका की तरह कुछ संदर्भित करते हैं। क्या उनका मतलब पहचानकर्ता (परिवर्तनीय नाम, निरंतर नाम, फ़ंक्शन नाम) हैं?

प्रतीक तालिका एक सारणी है जो मूल्यों (संख्याओं, ऑफसेट, पते) के प्रतीक को मानचित्र करती है। आपके पहचानकर्ताओं के लिए कुछ प्रतीक हैं, लेकिन अन्य उपयोगों के लिए भी अधिक कुछ हैं। आपके पहचानकर्ताओं को प्रतीक बनने के लिए अधिक या कम संशोधित किया जा सकता है, अधिकांशतः नाम झड़पों को रोकने के लिए (उदा। "_" की पूर्ति)।

लिंकर के पास प्रतीक तालिका मुद्रित करने के लिए एक विकल्प - प्रिंट-मानचित्र है। यदि आप लिंकिंग के लिए जीसीसी का उपयोग करते हैं तो आप -Wl, - प्रिंट-मानचित्र का उपयोग कर सकते हैं।

यदि आपको निम्न स्तर की तकनीकी सामग्री पसंद है तो आपको एम्बेडेड प्रोग्रामिंग पर एक नज़र डालना चाहिए, यानी प्रोग्रामिंग माइक्रोकंट्रोलर जो विभिन्न इलेक्ट्रिक उपकरणों में उपयोग किए जाते हैं। विंडोज़ जैसे डेस्कटॉप सिस्टम के लिए आपको सामान्य रूप से इस तरह के विवरण देखने की आवश्यकता नहीं होती है।

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