2009-12-31 9 views
6

मैं एक नौसिखिया प्रोग्रामर हूं। मैं सिर्फ & लिंकिंग को जोड़कर, विभिन्न चरणों संकलन पर आउटपुट देखना चाहता था। मैं असेंबली भाषा भी नहीं जानता।किसी प्रोग्राम में पहचानकर्ताओं के साथ क्या होता है?

मैं एक साधारण प्रोग्राम

#include <stdio.h> 

int humans = 9; 

int main() 
{ 
     int lions = 2; 
     int cubs = populate(lions); 
     return 0; 
} 

int populate(int crappyVariable) 
{ 
    return ++crappyVariable; 
} 

मैं gcc - S sample.c मैं विधानसभा भाषा के उत्पादन से हैरान हूँ इस्तेमाल किया लिखा था। मैंने सभी परिवर्तनीय नाम & फ़ंक्शन नाम खो दिए।

यह मनुष्यों, जनसंख्या, मुख्य जैसे वैश्विक पहचानकर्ताओं को संरक्षित करता है लेकिन यह उन्हें अंडरस्कोर _ के साथ उपसर्ग करता है। तो, मैं पहचानकर्ताओं का उपयोग करने के रूप में इसे विचार नहीं करूँगा। वैसे भी, बिंदु यह सभी पहचानकर्ता खो दिया है।

मेरा प्रश्न यह है कि यह फ़ंक्शन कैसे कॉल करेगा या चर का संदर्भ देगा?

मैं आउटपुट के आगे के चरणों के बारे में वास्तव में उत्सुक हूं, जो बाइनरी में होगा (जो देखने योग्य नहीं है)।

लिंक करने से पहले & को इकट्ठा करने के बाद आउटपुट कैसे होगा? मुझे लगता है कि यह अंडरस्कोर प्रीफिक्स्ड ग्लोबल आइडेंटिफायर भी खोलेगा? फिर फिर सवाल यह है कि यह कार्यों को कैसे कॉल करेगा या संचालन के लिए चर का संदर्भ देगा?

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

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

संपादित करें: प्रतिक्रिया में, टिप्पणी के लिए। मैंने अपने प्रश्न को कई प्रश्नों में तोड़ दिया। यहां इस प्रश्न का दूसरा भाग दिया गया है: not clear with the job of the linker

+4

आप इस के साथ बेहतर किस्मत हो सकता है अगर आप इसे अलग अलग सवाल में अलग पर महान मुक्त Linkers और लोडर पुस्तक http://www.iecc.com/linker/ अधिक जानकारी के लिए देखें। एक ही जवाब में इस ज़मीन को ढंकना शायद ज्यादातर लोगों की तुलना में अधिक है - मेरे साथ - अपने खाली समय में करने के लिए तैयार हैं। – tvanfosson

+1

मुझे खेद है। मैंने इसके बारे में नहीं सोचा था। मैं बहुत उलझन में था। तो बस लिखने पर रखा। मैं कई पदों में तोड़ने की कोशिश करूंगा। – Alice

उत्तर

3

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

यदि आप "असेंबलर" विकल्प या डिस्सेबल कोड के साथ संकलित करते हैं, तो आप कुछ पहचानकर्ता देख सकते हैं; वे कोड के चारों ओर अपना रास्ता खोजने में आपकी सहायता के लिए हैं, क्योंकि आप अपने सिर में अनावश्यक रूप से डेटा/कोड ऑफसेट कंप्यूटिंग करने की अपेक्षा नहीं कर रहे हैं।

लिंकिंग के बारे में आपके प्रश्न का उत्तर देने के लिए: लेबल और पहचानकर्ता जिन्हें केवल "प्रोग्राम" के अंदर "अंदर" उपयोग किया जाता है, प्रोग्राम को स्थानांतरित करने योग्य ऑब्जेक्ट फ़ॉर्म में संकलित करने के बाद चला जाता है। हालांकि, बाहरी परिभाषित नाम, जैसे main() की आवश्यकता है क्योंकि बाहरी मॉड्यूल उन्हें संदर्भित करेंगे; इसलिए एक संकलित ऑब्जेक्ट फ़ाइल में बाहरी रूप से दृश्यमान नामों की एक छोटी तालिका होगी और वे किस स्थान का संदर्भ लेंगे। एक लिंकर तब उन मॉडलों के आधार पर आपके मॉड्यूल में बाहरी संदर्भों को जोड़ सकता है (और इसके विपरीत)।

लिंक करने के बाद, बाहरी रूप से परिभाषित नामों की भी आवश्यकता नहीं है। यदि आप डीबग विकल्पों के साथ संकलित करते हैं, तो अंतिम प्रोग्राम से नामों की तालिकाओं को अभी भी जोड़ा जा सकता है, हालांकि, आप अपने प्रोग्राम को डीबग करते समय उन नामों का उपयोग कर सकते हैं।

2

आपको वास्तव में कंपाइलर्स और कंपाइलर डिज़ाइन पर पढ़ने की आवश्यकता है। http://www.freetechbooks.com/compiler-design-and-construction-f14.html

के साथ प्रारंभ करें सारांश यहां दिया गया है।

लक्ष्य यह है कि सामान को स्मृति में कॉपी किया जाए जो निष्पादित और चलाएगा। फिर ओएस हाथ उस सामान पर नियंत्रण रखता है।

"लोडर" प्रतियों को विभिन्न फ़ाइलों से स्मृति में कॉपी करता है। ये फ़ाइलें वास्तव में एक प्रकार की भाषा है जो बताती है कि सामान स्मृति में कहां जाता है और उन स्थानों में क्या होता है। यह एक तरह की "लोड मेमोरी" भाषा है।

कंपाइलर और लिंकर का काम उन फ़ाइलों को बनाना है जो लोडर को सही काम करेंगे।

कंपाइलर का आउटपुट "ऑब्जेक्ट" फाइल है - अनिवार्य रूप से कई बाहरी खंडों वाली कई छोटी खंडित फ़ाइलों में लोडर निर्देश। कंपाइलर का आउटपुट आदर्श रूप से बाहरी संदर्भों के लिए प्लेस धारकों के साथ कुछ मशीन कोड है। सभी आंतरिक संदर्भों को हेप मेमोरी या स्टैक फ्रेम या फ़ंक्शन नामों में ऑफ़सेट के रूप में हल किया गया है।

लिंकर का आउटपुट कम बाहरी संदर्भों के साथ बड़ी लोडर फाइलें है। यह काफी हद तक प्रारूप में संकलक के आउटपुट के समान है। कुछ विवरण http://linux.about.com/library/cmd/blcmdl1_nm.htm

यहाँ: लेकिन इसे और अधिक में मुड़ा हुआ सामान है

ld आदेश पर इस पढ़ें:। http://linux.about.com/library/cmd/blcmdl1_ld.htm

एनएम आदेश पर इस पढ़ें।

"... यह फ़ंक्शन कैसे कॉल करेगा या चर का संदर्भ देगा?"

फ़ंक्शन नाम, आमतौर पर उत्पादन के उत्पादन के बाद के चरणों तक संरक्षित होते हैं।

परिवर्तनीय नाम किसी और चीज में परिवर्तित हो जाते हैं। "ग्लोबल" वैरिएबल को आवंटित आवंटित किया जाता है और कंपाइलर के पास वैरिएबल नाम से टाइप करने के लिए स्थिर ("हीप") मेमोरी में ऑफसेट होता है।

फ़ंक्शन के भीतर स्थानीय चर (आमतौर पर) स्टैक फ्रेम में आवंटित होते हैं। कंपाइलर में वैरिएबल नाम से टाइप करने के लिए स्टैक फ्रेम में ऑफ़सेट करने के लिए एक नक्शा है। जब फ़ंक्शन दर्ज किया जाता है, तो आवश्यक आकार का एक स्टैक फ्रेम आवंटित किया जाता है और वेरिएबल बस उस फ्रेम में ऑफ़सेट होते हैं।

"... यह कार्यों को कैसे कॉल करेगा या संचालन के लिए चर का संदर्भ देगा?"

आपको कंपाइलर को संकेत देना होगा। extern कीवर्ड संकलक को बताता है कि इस मॉड्यूल में एक नाम परिभाषित नहीं किया गया है, लेकिन किसी अन्य मॉड्यूल में परिभाषित किया गया है और संदर्भ को लिंक (या लोड) समय पर हल किया जाना चाहिए।

"... अगर वहाँ से जोड़ने के लिए कुछ भी नहीं है ..."

यह कभी नहीं सच है। आपका कार्यक्रम कुल निष्पादन योग्य का केवल एक टुकड़ा है। अधिकांश सी पुस्तकालयों में वास्तविक मुख्य प्रोग्राम शामिल है जो तब आपके मुख्य कार्य को "मुख्य" कहते हैं।

"क्या लिंकर असेंबलर के ऑब्जेक्ट कोड आउटपुट को बदल देगा?"

यह ओएस के साथ बहुत भिन्न होता है। कई ओएस में लिंकर और लोडिंग सभी एक बार में होते हैं।अक्सर ऐसा होता है कि सी कंपाइलर से आउटपुट को वास्तव में बहुत अधिक रिज़ॉल्यूशन किए बिना संग्रह में फेंक दिया जाता है।

जब निष्पादन योग्य स्मृति में लोड किया जाता है, तो संग्रह संदर्भ और किसी बाहरी साझा ऑब्जेक्ट फ़ाइलों को भी लोड किया जाता है।

"कार्यक्रम नहीं चल रहा है, यह केवल विनिर्माण चरण में है।"

इसका कोई मतलब नहीं है। निश्चित नहीं है कि आप इसे क्यों शामिल कर रहे हैं।

"लिंकर मेमोरी को कैसे मैप कर सकता है? यह कैसा दिखता है?"

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

"यह रन टाइम सही है?"

डीबग - रन टाइम का यही एकमात्र तरीका है। इसका मतलब कुछ और नहीं हो सकता है, या यह डिबगिंग नहीं है।

+0

"कार्यक्रम नहीं चल रहा है, यह सिर्फ विनिर्माण चरण में है।" मेरा मतलब है कि मैंने लिखा सी प्रोग्राम अभी तक निष्पादन चरण में नहीं है।यह अभी भी निष्पादन योग्य – Alice

+0

बनने के अपने रास्ते पर है, ठीक है, आपकी फ़ाइल या तो स्रोत कोड फ़ाइल है, या इसे ऑब्जेक्ट कोड फ़ाइल में संकलित किया गया है, या इसे निष्पादन योग्य फ़ाइल में जोड़ा गया है। –

+0

@ एलिस: यह अभी भी अप्रासंगिक है; यह सब आपके प्रोग्राम को कभी भी चलने से पहले बहुत लंबा होता है। यह कहकर कि यह नहीं चल रहा है सहायक नहीं है। –

0

संख्या देखने के लिए स्थानीय चर विधानसभा कोड में नियंत्रित किया जाता है, जैसे कुछ संकलन:

int main() { int foo = 42; } 

क्या आप ध्यान देंगे है ही नहीं, कि चर नाम गायब हो जाता है, लेकिन जहां परिणामी डेटा चला जाता है। आपको कुछ ऐसा दिखाई देगा:

movq %rsp, %rbp 

जो वर्तमान स्टैक पॉइंटर पर बेस पॉइंटर सेट करता है। फिर:

movl $42, -4(%rbp) 

तो यह हमें बताता है कि संकलक ढेर पर कुछ जगह आवंटित करता है लेकिन इसे अनामित छोड़ देता है। Foo जैसे अधिक चर जोड़ना मूल रूप से बेस पॉइंटर के नीचे अधिक मेमोरी आवंटित करेगा। वेरिएबल जो "foo" था अब -4(%rbp) है।

0

जेनरेटेड पर ओजडम्पम्प-डी चलाने के लिए एक अच्छा अगला कदम है और इसे। संस्करण के साथ तुलना करें।

यह एक विचार देता है कि एस। क्या है, और बाइनरी में अनुवाद किया गया है।

अंतिम चरण लिंकिंग है, जिसका अर्थ है कि कई पास .o फाइलों के बीच सभी लेबलों को 0 या लोड पते के सापेक्ष पते पर हल करने के लिए लगभग दो पास हैं।

जोड़ने

+0

यह एक बहुत अच्छी सलाह है। मैं निश्चित रूप से यह करूँगा। मैं इस सामान के बारे में और जानना चाहता हूं। – Alice

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