2013-10-15 5 views
5

ओवरराइट करने नहीं देगा, मैं अस्थायी रूप से प्रयोग के लिए अपने स्वयं के ढेर का उपयोग करने के लिए कोड लिख रहा हूं। जब मैंने शाब्दिक इनलाइन असेंबली का इस्तेमाल किया तो यह काम करता था। मैं चरम स्थानों को हार्डकोड कर रहा था क्योंकि ऑफसेट्स को ईबीपी से बंद कर दिया गया था। हालांकि, मैं चाहता था कि मेरा कोड हार्ड कोड मेमोरी पतों में हाइविंग के बिना काम करे, इसलिए मैं जीसीसी की विस्तारित इनलाइन को देख रहा हूं।

volatile intptr_t new_stack_ptr = (intptr_t) MY_STACK_POINTER; 
volatile intptr_t old_stack_ptr = 0; 
asm __volatile__("movl %%esp, %0\n\t" 
     "movl %1, %%esp" 
     : "=r"(old_stack_ptr) /* output */ 
     : "r"(new_stack_ptr) /* input */ 
     ); 

इस की बात पहले चर old_stack_ptr में ढेर सूचक को बचाने के लिए है: क्या मैं पीछा कर रहा है। इसके बाद, स्टैक पॉइंटर (% esp) को उस पते के साथ ओवरराइट किया गया है जिसे मैंने new_stack_ptr में सहेजा है।

इसके बावजूद, मैंने पाया कि जीसीसी old esstack_ptr में% esp को सहेज रहा था, लेकिन% esp को new_stack_ptr के साथ बदल नहीं रहा था। ,

mov -0x14(%ebp),%eax 
mov %esp,%eax 
mov %eax,%esp 
mov %eax,-0x18(%ebp) 

मुझे लगता है कि जीसीसी esp% संरक्षित करने के लिए कोशिश कर रहा है, क्योंकि मैं यह स्पष्ट रूप से के रूप में घोषित की जरूरत नहीं है: गहरी निरीक्षण करने पर, मैंने पाया यह वास्तव में मेरे विधानसभा विस्तार किया है और उसके अपने निर्देश है, जो अनुसरण कर रहे हैं जोड़ा एक "आउटपुट" ऑपरेंड ... मैं इस के साथ पूरी तरह गलत हो सकता हूं ...

मैं वास्तव में ऐसा करने के लिए विस्तारित इनलाइन असेंबली का उपयोग करना चाहता था, क्योंकि यदि नहीं, ऐसा लगता है कि मुझे स्थान "हार्ड कोड" करना है असेंबली में% ebp से ऑफसेट्स, और मैं इस तरह के चर नामों का उपयोग करना चाहूंगा ... विशेष रूप से क्योंकि इस कोड को कुछ अलग-अलग प्रणालियों पर काम करने की ज़रूरत है, जो सभी मेरे चर अलग-अलग ऑफ़सेट करते हैं, इसलिए विस्तारित इनलाइन असेंबली का उपयोग करना मुझे स्पष्ट करने की अनुमति देता है y वैरिएबल लोकेशन कहता है ... लेकिन मुझे समझ में नहीं आता कि यह अतिरिक्त सामान क्यों कर रहा है और मुझे स्टैक पॉइंटर को ओवरराइट करने की इजाजत नहीं दे रहा था, जब से मैंने विस्तारित असेंबली का उपयोग शुरू किया था, यह ऐसा कर रहा है।

मैं किसी भी मदद की सराहना करता हूं !!!

+0

यह सुनिश्चित नहीं करता कि यह मदद करता है, लेकिन हो सकता है कि '-फॉमिट-फ्रेम-पॉइंटर' (जो '-O1' और ऊपर के साथ सक्षम है) '' ebp' के बारे में चिंता करने की आवश्यकता को खत्म कर देगा। – DaoWen

+0

अतिरिक्त सामान शायद वहां है क्योंकि आप डीबग (कोई अनुकूलन) निर्माण नहीं कर रहे हैं और जीसीसी डिफ़ॉल्ट त्रुटियों को पकड़ने के लिए डिफ़ॉल्ट रूप से करता है। जीसीसी द्वारा प्रदान किए जाने वाले विकल्प देखने के लिए "जीसीसी स्टैक फ़्रेम चेक" के लिए खोजें। – Skizz

उत्तर

8

ठीक है तो समस्या यह है कि जीसीसी एक ही रजिस्टर eax पर इनपुट और आउटपुट आवंटित कर रहा है। आप जीसीसी को बताना चाहते हैं कि आप इनपुट, उर्फ ​​का उपयोग करने से पहले उत्पादन को रोक रहे हैं। "Earlyclobber"।

asm __volatile__("movl %%esp, %0\n\t" 
     "movl %1, %%esp" 
     : "=&r"(old_stack_ptr) /* output */ 
     : "r"(new_stack_ptr) /* input */ 
     ); 

आउटपुट के लिए & साइन इन करें। यह आपके कोड को ठीक करना चाहिए।

अद्यतन: वैकल्पिक रूप से, तुम इतनी तरह एक ही रजिस्टर हो सकता है और xchg उपयोग करने के लिए, इनपुट और आउटपुट के लिए मजबूर कर सकता है:

asm __volatile__("xchg %%esp, %0\n\t" 
     : "=r"(old_stack_ptr) /* output */ 
     : "0"(new_stack_ptr) /* input */ 
     ); 

सूचना "0" कि कहते हैं, "तर्क के रूप में एक ही रजिस्टर में डाल 0 "।

+0

आपको बहुत बहुत धन्यवाद! मैंने पहले कभी जल्दी क्लॉबर के बारे में नहीं सुना था। उत्कृष्ट जवाब मैं वास्तव में इसकी प्रशंसा करता हूँ। यह तय है। – Chad

+1

मुझे लगता है कि वैकल्पिक रूप से आप केवल 'xchg' का उपयोग कर सकते हैं और उसके बाद उसी रजिस्टर में इनपुट और आउटपुट को मजबूर कर सकते हैं। – Jester

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