यहाँ किसी भी विषय के लिए आगे पढ़ने: लिनक्स सिस्टम कॉल के लिए निश्चित गाइड
मैंने लिनक्स पर GNU असेंबलर (गैस) का उपयोग करके इनका सत्यापन किया।
कर्नेल इंटरफ़ेस
x86-32 उर्फ i386 लिनक्स सिस्टम कॉल सम्मेलन:
लिनक्स सिस्टम कॉल के लिए x86-32 पैरामीटर में रजिस्टरों का उपयोग करके पारित किया जाता है। %eax
syscall_number के लिए। % ebx,% ecx,% edx,% esi,% edi,% ebp का उपयोग सिस्टम कॉल में 6 मापदंडों को पारित करने के लिए किया जाता है।
वापसी मूल्य में है %eax
। अन्य सभी रजिस्टर (EFLAGS सहित) भर में संरक्षित हैं int $0x80
।
मैंने लिनक्स असेंबली ट्यूटोरियल से स्निपेट का अनुसरण किया लेकिन मुझे इस बारे में संदेह है। यदि कोई एक उदाहरण दिखा सकता है, तो यह बहुत अच्छा होगा।
यदि छह से अधिक तर्क हैं,
%ebx
तो स्मृति स्थान होना चाहिए जहां तर्कों की सूची संग्रहीत है - लेकिन इस बारे में चिंता न करें क्योंकि यह संभावना नहीं है कि आप छह से अधिक तर्कों के साथ एक syscall का उपयोग करेंगे।
एक उदाहरण और थोड़ा और पढ़ने के लिए, http://www.int80h.org/bsdasm/#alternate-calling-conference को देखें । I386 लिनक्स के लिए हैलो वर्ल्ड का उपयोग करने का एक और उदाहरण int 0x80
: हैलो, लिनक्स सिस्टम कॉल के साथ असेंबली भाषा में दुनिया?
32-बिट सिस्टम कॉल करने का एक तेज़ तरीका है: उपयोग करना sysenter
। कर्नेल प्रत्येक प्रक्रिया (vDSO) में मेमोरी का एक पृष्ठ मैप करता है, sysenter
डांस के यूजर-स्पेस साइड के साथ , जिसे रिटर्न एड्रेस खोजने में सक्षम होने के लिए कर्नेल के साथ सहयोग करना होगा। मैपिंग रजिस्टर करने के लिए Arg समान है int $0x80
। आपको आमतौर पर sysenter
सीधे उपयोग करने के बजाय vDSO में कॉल करना चाहिए । ( VDSO में लिंक करने और कॉल करने की जानकारी के लिए लिनक्स सिस्टम कॉल के लिए निश्चित गाइड देखें , और अधिक जानकारी के लिए sysenter
, और सिस्टम कॉल के साथ करने के लिए बाकी सब कुछ।)
x86-32 [मुक्त | खुला | नेट | ड्रैगनफ़ली] बीएसडी यूनिक्स सिस्टम कॉल सम्मेलन:
स्टैक पर पैरामीटर पारित किए जाते हैं। स्टैक पर मापदंडों (अंतिम पैरामीटर को पहले धकेल दिया गया) को पुश करें। फिर अतिरिक्त 32-बिट डमी डेटा को धक्का दें (यह वास्तव में डमी डेटा नहीं है। अधिक जानकारी के लिए निम्न लिंक का संदर्भ लें) और फिर सिस्टम कॉल निर्देश देंint $0x80
http://www.int80h.org/bsdasm/#default-calling-convention
x86-64 लिनक्स सिस्टम कॉल कन्वेंशन:
x86-64 मैक ओएस एक्स समान है लेकिन अलग है । TODO: जाँच करें कि * BSD क्या करता है।
खंड का संदर्भ लें: "V.2 AMD64 लिनक्स कर्नेल कन्वेंशन" सिस्टम V एप्लिकेशन बाइनरी इंटरफ़ेस AMD64 आर्किटेक्चर प्रोसेसर सप्लीमेंट । I386 और x86-64 सिस्टम V psABI के नवीनतम संस्करणों को इस पृष्ठ से ABI अनुचर के रेपो में जोड़ा जा सकता है । (यह भी देखें86 टैग ABI लिंक के लिए विकी और x86 asm के बारे में अन्य अच्छे सामान के बहुत सारे।)
यहाँ इस अनुभाग से स्निपेट दिया गया है:
- उपयोगकर्ता-स्तरीय अनुप्रयोग अनुक्रम% rdi,% rsi,% rdx,% rcx,% r8 और% r9 को पास करने के लिए पूर्णांक रजिस्टर के रूप में उपयोग करते हैं। कर्नेल इंटरफ़ेस% rdi,% rsi,% rdx,% r10,% r8 और% r9 का उपयोग करता है।
syscall
निर्देश के माध्यम से एक सिस्टम-कॉल किया जाता है । यह क्लॉबर्स% आरसीएक्स और% आर 11 और साथ ही% रैक्स रिटर्न वैल्यू है, लेकिन अन्य रजिस्टर संरक्षित हैं।
- Syscall की संख्या को रजिस्टर% rax में पारित किया जाना है।
- सिस्टम-कॉल छह तर्कों तक सीमित हैं, कोई भी तर्क सीधे ढेर पर पारित नहीं होता है।
- Syscall से लौटते हुए, रजिस्टर% rax में सिस्टम-कॉल का परिणाम होता है। -4095 और -1 के बीच की सीमा में एक मूल्य एक त्रुटि को इंगित करता है, यह है
-errno
।
- वर्ग INTEGER या वर्ग MEMORY के केवल मान कर्नेल को दिए जाते हैं।
याद रखें कि यह लिनक्स-विशिष्ट परिशिष्ट से एबीआई तक है, और यहां तक कि लिनक्स के लिए यह जानकारीपूर्ण है न कि मानक। (लेकिन यह वास्तव में सही है।)
यह 32-बिट int $0x80
ABI है (लेकिन अत्यधिक अनुशंसित नहीं) 64-बिट कोड में प्रयोग करने योग्य। यदि आप 64-बिट कोड में 32-बिट int 0x80 लिनक्स ABI का उपयोग करते हैं तो क्या होगा? यह अभी भी 32-बिट के लिए अपने इनपुट को छोटा करता है, इसलिए यह संकेत के लिए अनुपयुक्त है, और यह r8-r11-z11 है।
उपयोगकर्ता इंटरफ़ेस: फ़ंक्शन कॉलिंग
x86-32 समारोह बुला सम्मेलन:
X86-32 में पैरामीटर स्टैक पर पारित किए गए थे। अंतिम पैरामीटर पहले स्टैक पर धकेल दिया गया था जब तक कि सभी पैरामीटर नहीं किए जाते हैं और फिर call
निर्देश निष्पादित किया गया था। यह असेंबली से लिनक्स पर सी लाइब्रेरी (libc) फ़ंक्शन को कॉल करने के लिए उपयोग किया जाता है।
I386 सिस्टम वी एबीआई (लिनक्स पर प्रयुक्त) के आधुनिक संस्करणों को %esp
ए से पहले 16-बाइट संरेखण की आवश्यकता होती है call
, जैसे कि x86-64 सिस्टम वी एबीआई को हमेशा आवश्यक होता है। Callees को यह मानने की अनुमति है कि SSE 16-बाइट लोड / स्टोर का उपयोग करता है जो कि बिना सोचे-समझे फॉल्ट करता है। लेकिन ऐतिहासिक रूप से, लिनक्स को केवल 4-बाइट स्टैक संरेखण की आवश्यकता होती है, इसलिए स्वाभाविक रूप से संरेखित स्थान को 8-बाइट double
या कुछ और के लिए आरक्षित करने के लिए अतिरिक्त काम करना पड़ा ।
कुछ अन्य आधुनिक 32-बिट सिस्टम को अभी भी 4 से अधिक बाइट स्टैक संरेखण की आवश्यकता नहीं है।
x86-64 सिस्टम V यूजर-स्पेस फंक्शन कॉलिंग कन्वेंशन:
x86-64 सिस्टम V पास रजिस्टरों में आर्ग्स करता है, जो कि i386 सिस्टम वी के स्टैक आर्ग्स कन्वेंशन की तुलना में अधिक कुशल है। यह मेमोरी (कैश) के लिए args के विलंबता और अतिरिक्त निर्देशों से बचता है और फिर उन्हें फिर से कैली में लोड करता है। यह अच्छी तरह से काम करता है क्योंकि अधिक रजिस्टर उपलब्ध हैं, और आधुनिक उच्च-प्रदर्शन सीपीयू के लिए बेहतर है जहां विलंबता और आउट-ऑफ-ऑर्डर निष्पादन मामला है। (I386 ABI बहुत पुराना है)।
इस नए तंत्र में: पहले मापदंडों को कक्षाओं में विभाजित किया गया है। प्रत्येक पैरामीटर का वर्ग उस तरीके को निर्धारित करता है जिसमें इसे कहा जाता है।
पूरी जानकारी के लिए देखें: "3.2 फंक्शन कॉलिंग सीक्वेंस" सिस्टम V एप्लीकेशन बाइनरी इंटरफेस AMD64 आर्किटेक्चर प्रोसेसर सप्लीमेंट जो भाग में पढ़ता है:
एक बार तर्क वर्गीकृत हो जाने के बाद, रजिस्टरों को (बाएं से दाएं क्रम में) नियत किया जाता है:
- यदि वर्ग मेमोरी है, तो स्टैक पर तर्क पास करें।
- यदि वर्ग INTEGER है, तो अनुक्रम% rdi,% rsi,% rdx,% rx,% r8 और% r9 का अगला उपलब्ध रजिस्टर उपयोग किया जाता है
तो विधानसभा से किसी भी libc फ़ंक्शन के लिए पूर्णांक / सूचक (यानी INTEGER वर्ग) मापदंडों को पारित करने के लिए उपयोग किए जाने %rdi, %rsi, %rdx, %rcx, %r8 and %r9
वाले रजिस्टर हैं । % REG का उपयोग पहले INTEGER पैरामीटर के लिए किया जाता है। 2% के लिए% rsi, 3 के लिए% rdx और इसी तरह। फिर निर्देश दिया जाए। निष्पादित होने पर स्टैक ( ) 16B-align होना चाहिए ।call
%rsp
call
यदि 6 से अधिक INTEGER पैरामीटर हैं, तो 7 वें INTEGER पैरामीटर और बाद में स्टैक पर पारित किए जाते हैं। (कॉलर पॉप, x86-32 के समान।)
पहले 8 फ्लोटिंग पॉइंट आर्ग्स% xmm0-7 में पास किए जाते हैं, बाद में स्टैक पर। कोई कॉल-संरक्षित वेक्टर रजिस्टर नहीं हैं। (एफपी और पूर्णांक तर्कों के मिश्रण के साथ एक समारोह में कुल 8 से अधिक रजिस्टर तर्क हो सकते हैं।)
वैरिएडिक फ़ंक्शंस ( जैसेprintf
) को हमेशा ज़रूरत होती है %al
= एफपी रजिस्टर संख्या की संख्या।
rdx:rax
स्मृति में रजिस्टरों ( वापसी पर) में संरचना को कब पैक करना है इसके लिए नियम हैं । विवरण के लिए एबीआई देखें, और यह सुनिश्चित करने के लिए संकलक आउटपुट की जांच करें कि आपका कोड संकलक के साथ सहमत है कि कुछ कैसे पारित / वापस किया जाना चाहिए।
ध्यान दें कि Windows x64 फ़ंक्शन कॉलिंग कन्वेंशन में x86-64 सिस्टम V से कई महत्वपूर्ण अंतर हैं, जैसे छाया स्थान जो कॉलर (एक रेड-ज़ोन के बजाय) और आरक्षित-संरक्षित xmm6-xmm15 द्वारा आरक्षित होना चाहिए। और बहुत अलग नियम जिसके लिए arg किस रजिस्टर में जाता है।