इसे कहां धकेला गया है?
esp - 4
। ज्यादा ठीक:
esp
4 से घटाया जाता है
- मान को धकेल दिया जाता है
esp
pop
इससे उलट होता है।
सिस्टम V ABI लिनक्स को rsp
एक समझदार स्टैक स्थान पर इंगित करने के लिए कहता है जब प्रोग्राम चालू होता है: प्रोग्राम लॉन्च होने पर डिफ़ॉल्ट रजिस्टर स्थिति क्या होती है (asm, linux)? जो आप आमतौर पर उपयोग करना चाहिए।
आप किसी रजिस्टर को कैसे धकेल सकते हैं?
न्यूनतम जीएनयू जीएएस उदाहरण:
.data
/* .long takes 4 bytes each. */
val1:
/* Store bytes 0x 01 00 00 00 here. */
.long 1
val2:
/* 0x 02 00 00 00 */
.long 2
.text
/* Make esp point to the address of val2.
* Unusual, but totally possible. */
mov $val2, %esp
/* eax = 3 */
mov $3, %ea
push %eax
/*
Outcome:
- esp == val1
- val1 == 3
esp was changed to point to val1,
and then val1 was modified.
*/
pop %ebx
/*
Outcome:
- esp == &val2
- ebx == 3
Inverses push: ebx gets the value of val1 (first)
and then esp is increased back to point to val2.
*/
GitHub पर उपर्युक्त जोर के साथ ।
इसकी आवश्यकता क्यों है?
यह सच है कि उन निर्देशों को आसानी से लागू किया जा सकता है mov
, add
और sub
।
वे कारण हैं कि वे मौजूद हैं, यह है कि निर्देशों के संयोजन इतने लगातार होते हैं, कि इंटेल ने उन्हें हमारे लिए प्रदान करने का फैसला किया।
उन संयोजनों में अक्सर ऐसा क्यों होता है, इसका कारण यह है कि वे रजिस्टरों के मूल्यों को स्मृति में सहेजने और पुनर्स्थापित करने के लिए अस्थायी रूप से आसान बनाते हैं ताकि वे अधिलेखित न हों।
समस्या को समझने के लिए, हाथ से कुछ सी कोड संकलित करने का प्रयास करें।
एक बड़ी कठिनाई, यह तय करना है कि प्रत्येक चर कहाँ संग्रहीत किया जाएगा।
आदर्श रूप से, सभी चर रजिस्टरों में फिट होंगे, जो कि एक्सेस करने के लिए सबसे तेज़ मेमोरी है (वर्तमान में रैम की तुलना में लगभग 100 गुना तेज है)।
लेकिन निश्चित रूप से, हमारे पास रजिस्टरों की तुलना में अधिक चर आसानी से हो सकते हैं, विशेष रूप से नेस्टेड फ़ंक्शन के तर्कों के लिए, इसलिए इसका एकमात्र समाधान मेमोरी में लिखना है।
हम किसी भी मेमोरी पते पर लिख सकते हैं, लेकिन चूंकि फ़ंक्शन के स्थानीय चर और तर्क कॉल और रिटर्न एक अच्छे स्टैक पैटर्न में फिट होते हैं, जो मेमोरी फ़्रेग्मेंटेशन को रोकता है, जो इससे निपटने का सबसे अच्छा तरीका है। तुलना करें कि ढेर आवंटन लिखने के पागलपन के साथ।
फिर हम संकलक को हमारे लिए रजिस्टर आवंटन का अनुकूलन करने देते हैं, क्योंकि यह एनपी पूर्ण है, और संकलक लिखने के सबसे कठिन भागों में से एक है। इस समस्या को रजिस्टर आवंटन कहा जाता है , और यह ग्राफ़िकल रंग के लिए आइसोमोर्फिक है ।
जब कंपाइलर के आवंटनकर्ता को केवल रजिस्टरों के बजाय मेमोरी में चीजों को स्टोर करने के लिए मजबूर किया जाता है, जिसे एक स्पिल के रूप में जाना जाता है ।
क्या यह एकल प्रोसेसर निर्देश को उबालता है या यह अधिक जटिल है?
हम सभी को निश्चित रूप से पता है कि इंटेल push
एक pop
निर्देश और एक निर्देश है, इसलिए वे उस अर्थ में एक निर्देश हैं।
आंतरिक रूप से, इसे कई माइक्रोकोड में विस्तारित किया जा सकता है, एक को संशोधित करने esp
और एक को मेमोरी आईओ करने के लिए, और कई चक्र लेने के लिए।
लेकिन यह भी संभव है कि एक एकल push
अन्य निर्देशों के समतुल्य संयोजन से तेज हो, क्योंकि यह अधिक विशिष्ट है।
यह ज्यादातर संयुक्त राष्ट्र (डेर) प्रलेखित है:
b
,w
,l
, याq
स्मृति के आकार चालाकी से किया जा रहा निरूपित करने के लिए। उदाहरण के लिए:pushl %eax
औरpopl %eax