2013-08-02 5 views
17

के माध्यम से कौन से रजिस्टरों को संरक्षित किया जाता है, मुझे विश्वास है कि मैं समझता हूं कि लिनक्स x86-64 एबीआई रजिस्ट्रार का उपयोग करता है और फ़ंक्शन पर पैरामीटर पास करने के लिए स्टैक करता है (सीएफ previous ABI discussion)। मैं इस बारे में उलझन में हूं कि फ़ंक्शन कॉल में कौन से रजिस्टरों को संरक्षित किया जाना अपेक्षित है। यही है, किस रजिस्ट्रार को गठबंधन नहीं किया जाता है?लिनक्स x86-64 फ़ंक्शन कॉल

उत्तर

39

यहाँ रजिस्टरों की पूरी तालिका है और प्रलेखन [PDF Link] से उनके उपयोग:

table from docs

r12, r13, r14, r15, rbx, rsp, rbp कॉल प्राप्त करने वाला: सहेजे गए रजिस्टरों हैं - वे "फ़ंक्शन कॉल संरक्षित" कॉलम में "हां" है।

+0

उपरोक्त। बहुत धन्यवाद! – boneheadgeek

+0

झंडे के बारे में क्या? डीएफ की तरह? – socketpair

+2

@socketpair: किसी भी कॉल या वापसी से पहले डीएफ को अनसेट होना चाहिए, इसलिए गिनती-ऊपर के व्यवहार को 'cld' के बिना माना जा सकता है। हालत झंडे (जेडएफ की तरह) कॉल-क्लॉब्बेड हैं। मैं वास्तव में भूल जाता हूं कि एबीआई दस्तावेज़ एफपी राउंडिंग मोड और denormals के बारे में क्या कहते हैं-शून्य हैं। हो सकता है कि कोई फ़ंक्शन उन्हें संशोधित करता है, तो उसे लौटने से पहले पिछले राज्य को सहेजना/पुनर्स्थापित करना होगा, लेकिन ** एफपी भाग ** के लिए मेरा शब्द न लें। –

4

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

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

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

नियम परिभाषित करते हैं कि मानक-अनुरूप सॉफ्टवेयर कैसे मिल सकता है। हालांकि, यह कोड इन नियमों द्वारा खेलना (या उत्पन्न) कोड लिखना पूरी तरह से कानूनी है! कंपाइलर हर समय ऐसा करते हैं, क्योंकि वे जानते हैं कि कुछ परिस्थितियों में नियमों का पालन करने की आवश्यकता नहीं है।

static foo(int x); 

संकलन समय में, संकलक 100% निश्चित है कि इस समारोह केवल फ़ाइल में अन्य कोड से कहा जा सकता है:

इस प्रकार है उदाहरण के लिए, एक सी समारोह नामित foo कि घोषित किया जाता है पर विचार (एस) यह वर्तमान में संकलन कर रहा है। फंक्शन foo किसी और चीज द्वारा कभी भी नहीं कहा जा सकता है, इसकी परिभाषा दी गई है कि इसका मतलब स्थिर होना है। चूंकि संकलक संकलन समय पर foo के सभी कॉलर्स को जानता है, इसलिए संकलक जो भी कॉलिंग अनुक्रम चाहता है उसका उपयोग करने के लिए स्वतंत्र है (foo के कॉलर में foo के कोड को रेखांकित करने के लिए,

असेंबली कोड के लेखक के रूप में, आप यह भी कर सकते हैं।यही है, आप दो या दो से अधिक दिनचर्या के बीच एक "निजी समझौता" लागू कर सकते हैं, जब तक कि यह समझौता मानक-अनुरूप सॉफ्टवेयर की अपेक्षाओं में हस्तक्षेप नहीं करता है या उल्लंघन नहीं करता है।

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