एक संकलक स्टैक का प्रबंधन कैसे करता है और स्टैक पर मान कैसे एक्सेस किए जाते हैं, इसका एक ठोस उदाहरण प्रदान करने के लिए, हम विज़ुअल चित्रणों को देख सकते हैं, साथ ही GCC
लिनक्स वातावरण में i386 के साथ लक्ष्य आर्किटेक्चर के रूप में उत्पन्न कोड ।
1. स्टैक फ्रेम
जैसा कि आप जानते हैं, स्टैक एक रनिंग प्रोसेस के एड्रेस स्पेस में एक स्थान है, जिसका उपयोग फ़ंक्शंस या प्रक्रियाओं द्वारा किया जाता है , इस अर्थ में कि स्थानीय रूप से घोषित किए गए चरों के लिए स्टैक पर स्थान आवंटित किया जाता है, साथ ही फ़ंक्शन को पास किए गए तर्क () किसी भी फ़ंक्शन (यानी वैश्विक चर) के बाहर घोषित चर के लिए जगह को वर्चुअल मेमोरी में एक अलग क्षेत्र में आवंटित किया जाता है। किसी फ़ंक्शन के सभी डेटा के लिए आवंटित स्थान को स्टैक फ्रेम में संदर्भित किया जाता है । यहाँ कई स्टैक फ़्रेमों का दृश्य चित्रण किया गया है ( कंप्यूटर सिस्टम से: एक प्रोग्रामर का परिप्रेक्ष्य ):
2. स्टैक फ्रेम प्रबंधन और चर स्थान
संकलक द्वारा प्रबंधित और पढ़े जाने के लिए एक विशेष स्टैक फ्रेम के भीतर स्टैक के लिए लिखे गए मानों के लिए, इन मानों की स्थिति की गणना करने और उनके मेमोरी एड्रेस को पुनः प्राप्त करने के लिए कुछ विधि होनी चाहिए। सीपीयू में रजिस्टरों को स्टैक पॉइंटर के रूप में संदर्भित किया जाता है और बेस पॉइंटर इसकी मदद करता है।
बेस पॉइंटर, ebp
कन्वेंशन द्वारा, स्टैक के नीचे, या बेस का मेमोरी एड्रेस होता है। स्टैक फ्रेम के भीतर सभी मानों की स्थिति की गणना एक संदर्भ के रूप में आधार पॉइंटर में पते का उपयोग करके की जा सकती है। यह ऊपर चित्र में दर्शाया गया है: %ebp + 4
उदाहरण के लिए, बेस पॉइंटर प्लस 4 में संग्रहीत मेमोरी एड्रेस है।
3. कंपाइलर-जनरेटेड कोड
लेकिन मुझे जो नहीं मिलता है वह यह है कि स्टैक पर वेरिएबल्स को एक एप्लिकेशन द्वारा कैसे पढ़ा जाता है- अगर मैं x को पूर्णांक के रूप में घोषित करता हूं और असाइन करता हूं, तो x = 3 कहते हैं, और स्टैक पर संग्रहण आरक्षित होता है और फिर इसका मान 3 संग्रहीत किया जाता है वहाँ, और फिर उसी फ़ंक्शन में मैं y घोषित करता हूं और असाइन करता हूं, 4 कहता हूं, और फिर उसके बाद मैं x का उपयोग किसी अन्य अभिव्यक्ति में करता हूं, (z = 5 + x) कहूं कि जब z का मूल्यांकन करने के लिए प्रोग्राम x को कैसे पढ़ सकता है? यह स्टैक पर y के नीचे है?
आइए C में लिखे गए एक सरल उदाहरण कार्यक्रम का उपयोग करें कि यह कैसे काम करता है:
int main(void)
{
int x = 3;
int y = 4;
int z = 5 + x;
return 0;
}
आइए इस C स्रोत पाठ के लिए GCC द्वारा निर्मित असेंबली पाठ की जांच करें (मैंने स्पष्टता के लिए इसे थोड़ा साफ किया:)
main:
pushl %ebp # save previous frame's base address on stack
movl %esp, %ebp # use current address of stack pointer as new frame base address
subl $16, %esp # allocate 16 bytes of space on stack for function data
movl $3, -12(%ebp) # variable x at address %ebp - 12
movl $4, -8(%ebp) # variable y at address %ebp - 8
movl -12(%ebp), %eax # write x to register %eax
addl $5, %eax # x + 5 = 9
movl %eax, -4(%ebp) # write 9 to address %ebp - 4 - this is z
movl $0, %eax
leave
हम जो निरीक्षण करते हैं, वह यह है कि चर x, y और z क्रमशः %ebp - 12
, %ebp -8
और पते पर स्थित %ebp - 4
हैं। दूसरे शब्दों में, सीपीयू रजिस्टर में सहेजे गए मेमोरी एड्रेस का उपयोग करके स्टैक फ्रेम के भीतर चर के स्थानों की main()
गणना की जाती है %ebp
।
4. स्टैक पॉइंटर से परे मेमोरी में डेटा दायरे से बाहर है
मुझे स्पष्ट रूप से कुछ याद आ रहा है। क्या यह है कि स्टैक पर स्थान केवल चर के जीवनकाल / दायरे के बारे में है, और यह कि पूरे स्टैक वास्तव में हर समय कार्यक्रम के लिए सुलभ है? यदि हां, तो क्या इसका मतलब यह है कि कुछ अन्य सूचकांक हैं जो मानों को पुनः प्राप्त करने के लिए स्टैक पर केवल चर के पते रखते हैं? लेकिन फिर मुझे लगा कि स्टैक का पूरा बिंदु यह था कि मान वैरिएबल पते के समान ही संग्रहीत किए गए थे?
स्टैक वर्चुअल मेमोरी में एक क्षेत्र है, जिसका उपयोग कंपाइलर द्वारा प्रबंधित किया जाता है। कंपाइलर कोड को इस तरह से उत्पन्न करता है कि स्टैक पॉइंटर से परे मान (स्टैक के शीर्ष से आगे के मान) को कभी संदर्भित नहीं किया जाता है। जब किसी फ़ंक्शन को बुलाया जाता है, तो स्टैक पॉइंटर की स्थिति स्टैक पर जगह बनाने के लिए बदलती है जिसे "सीमा से बाहर" नहीं माना जाता है, इसलिए बोलने के लिए।
जैसा कि फ़ंक्शन कहा जाता है और वापस लौटता है, स्टैक पॉइंटर को घटाया और बढ़ाया जाता है। के बाद यह क्षेत्र से बाहर है ढेर के लिए लिखा डाटा गायब नहीं है, लेकिन संकलक इस डेटा को संदर्भित निर्देश उत्पन्न नहीं करता है संकलक का उपयोग कर इन आंकड़ों के पतों की गणना करने के लिए कोई रास्ता नहीं है क्योंकि वहाँ %ebp
या %esp
।
5. सारांश
कोड जिसे सीधे सीपीयू द्वारा निष्पादित किया जा सकता है, संकलक द्वारा उत्पन्न किया जाता है। कंपाइलर फ़ंक्शन और CPU रजिस्टरों के लिए स्टैक, स्टैक फ़्रेम का प्रबंधन करता है। I386 आर्किटेक्चर पर निष्पादित करने के उद्देश्य से कोड में स्टैक फ्रेम में चर के स्थानों को ट्रैक करने के लिए जीसीसी द्वारा उपयोग की जाने वाली एक रणनीति स्टैक फ्रेम बेस पॉइंटर में मेमोरी एड्रेस का उपयोग करना है, स्टैक फ्रेम %ebp
में स्थानों के लिए चर के संदर्भ और वैल्यू मान लिखें। पते के लिए ऑफ़सेट में %ebp
।