I386 और x86-64 पर UNIX और Linux सिस्टम कॉल के लिए कॉलिंग कन्वेंशन क्या हैं


147

निम्नलिखित लिंक दोनों UNIX (BSD स्वाद) और लिनक्स के लिए x86-32 सिस्टम कॉल सम्मेलनों की व्याख्या करें:

लेकिन दोनों UNIX & Linux पर x86-64 सिस्टम कॉल कन्वेंशन क्या हैं?


यूनिक्स कॉलिंग सम्मेलनों के लिए कोई "मानक" नहीं है। लिनक्स के लिए यकीन है, लेकिन मुझे यकीन है कि सोलारिस, ओपनबीएसडी, लिनक्स और मिनिक्स में शायद कम से कम थोड़ा अलग कॉलिंग कन्वेंशन हैं और वे सभी यूनिक्स हैं।
अर्लज़

2
यह पूरी तरह से सच नहीं है - अधिकांश मशीन प्रकारों के लिए उपलब्ध UNIX ABI का एक सेट है, जो C कंपाइलरों को इंटरऑपरेबिलिटी प्राप्त करने की अनुमति देता है। C ++ कंपाइलर्स में एक बड़ी समस्या है।
जोनाथन लेफ़लर

1
आप दोनों सही हैं। मैं FreeBSD और Linux के लिए देख रहा हूँ।
पंजे

मैं इस बात की सराहना करूंगा कि यदि उत्तर में इस बात की जानकारी हो कि रजिस्टर सिस्टम कॉल के लिए क्या संरक्षित हैं। बेशक स्टैक पॉइंटर है, (जब तक कि __NR_clone कॉल में एक नियंत्रित तरीके से नहीं बदला जाता), लेकिन क्या उनके अन्य हैं?
अल्बर्ट वैन डर हॉर्स्ट

@AlbertvanderHorst: हाँ, मैंने अभी 32bit के विवरण के साथ विकि उत्तर को अद्यतन किया है। 64 बिट पहले से ही सटीक था: जिस तरह से sysretकाम करता है, आरएक्स और आर 11 को नष्ट कर दिया जाता है , साथ ही रक्स को वापसी मूल्य के साथ बदल दिया जाता है। अन्य सभी रजिस्टर am64 पर संरक्षित हैं।
पीटर कॉर्ड्स

जवाबों:


230

यहाँ किसी भी विषय के लिए आगे पढ़ने: लिनक्स सिस्टम कॉल के लिए निश्चित गाइड


मैंने लिनक्स पर GNU असेंबलर (गैस) का उपयोग करके इनका सत्यापन किया।

कर्नेल इंटरफ़ेस

x86-32 उर्फ ​​i386 लिनक्स सिस्टम कॉल सम्मेलन:

लिनक्स सिस्टम कॉल के लिए x86-32 पैरामीटर में रजिस्टरों का उपयोग करके पारित किया जाता है। %eaxsyscall_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 अनुचर के रेपो में जोड़ा जा सकता है । (यह भी देखें टैग ABI लिंक के लिए विकी और x86 asm के बारे में अन्य अच्छे सामान के बहुत सारे।)

यहाँ इस अनुभाग से स्निपेट दिया गया है:

  1. उपयोगकर्ता-स्तरीय अनुप्रयोग अनुक्रम% rdi,% rsi,% rdx,% rcx,% r8 और% r9 को पास करने के लिए पूर्णांक रजिस्टर के रूप में उपयोग करते हैं। कर्नेल इंटरफ़ेस% rdi,% rsi,% rdx,% r10,% r8 और% r9 का उपयोग करता है।
  2. syscallनिर्देश के माध्यम से एक सिस्टम-कॉल किया जाता है । यह क्लॉबर्स% आरसीएक्स और% आर 11 और साथ ही% रैक्स रिटर्न वैल्यू है, लेकिन अन्य रजिस्टर संरक्षित हैं।
  3. Syscall की संख्या को रजिस्टर% rax में पारित किया जाना है।
  4. सिस्टम-कॉल छह तर्कों तक सीमित हैं, कोई भी तर्क सीधे ढेर पर पारित नहीं होता है।
  5. Syscall से लौटते हुए, रजिस्टर% rax में सिस्टम-कॉल का परिणाम होता है। -4095 और -1 के बीच की सीमा में एक मूल्य एक त्रुटि को इंगित करता है, यह है -errno
  6. वर्ग INTEGER या वर्ग MEMORY के केवल मान कर्नेल को दिए जाते हैं।

याद रखें कि यह लिनक्स-विशिष्ट परिशिष्ट से एबीआई तक है, और यहां तक ​​कि लिनक्स के लिए यह जानकारीपूर्ण है न कि मानक। (लेकिन यह वास्तव में सही है।)

यह 32-बिट int $0x80ABI है (लेकिन अत्यधिक अनुशंसित नहीं) 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 आर्किटेक्चर प्रोसेसर सप्लीमेंट जो भाग में पढ़ता है:

एक बार तर्क वर्गीकृत हो जाने के बाद, रजिस्टरों को (बाएं से दाएं क्रम में) नियत किया जाता है:

  1. यदि वर्ग मेमोरी है, तो स्टैक पर तर्क पास करें।
  2. यदि वर्ग 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%rspcall

यदि 6 से अधिक INTEGER पैरामीटर हैं, तो 7 वें INTEGER पैरामीटर और बाद में स्टैक पर पारित किए जाते हैं। (कॉलर पॉप, x86-32 के समान।)

पहले 8 फ्लोटिंग पॉइंट आर्ग्स% xmm0-7 में पास किए जाते हैं, बाद में स्टैक पर। कोई कॉल-संरक्षित वेक्टर रजिस्टर नहीं हैं। (एफपी और पूर्णांक तर्कों के मिश्रण के साथ एक समारोह में कुल 8 से अधिक रजिस्टर तर्क हो सकते हैं।)

वैरिएडिक फ़ंक्शंस ( जैसेprintf ) को हमेशा ज़रूरत होती है %al= एफपी रजिस्टर संख्या की संख्या।

rdx:raxस्मृति में रजिस्टरों ( वापसी पर) में संरचना को कब पैक करना है इसके लिए नियम हैं । विवरण के लिए एबीआई देखें, और यह सुनिश्चित करने के लिए संकलक आउटपुट की जांच करें कि आपका कोड संकलक के साथ सहमत है कि कुछ कैसे पारित / वापस किया जाना चाहिए।


ध्यान दें कि Windows x64 फ़ंक्शन कॉलिंग कन्वेंशन में x86-64 सिस्टम V से कई महत्वपूर्ण अंतर हैं, जैसे छाया स्थान जो कॉलर (एक रेड-ज़ोन के बजाय) और आरक्षित-संरक्षित xmm6-xmm15 द्वारा आरक्षित होना चाहिए। और बहुत अलग नियम जिसके लिए arg किस रजिस्टर में जाता है।


1
32 लाइन में "कुल्हाड़ी बीएक्स सीडी डीएक्स सी डी बीपी को छोड़कर सभी रजिस्टर संरक्षित हैं"। मैं किसी के बारे में नहीं सोच सकता ...
अल्बर्ट वैन डेर होर्स्ट

Amd64 पर, यदि 6 से अधिक पैरामीटर हैं और उन्हें स्टैक पर पारित किया जाता है, तो कॉल, कॉलर या कैली के बाद स्टैक की सफाई के लिए कौन जिम्मेदार है?
निकोलस

1
@ निकोलस: कॉलर स्टैक को साफ करता है। मैंने फ़ंक्शन-कॉलिंग सम्मेलन के बारे में अधिक विवरण के साथ उत्तर को अपडेट किया।
पीटर कॉर्ड्स

1
यदि आप int 0x8064-बिट कोड में Linux के ABI का उपयोग करते हैं , तो ठीक यही होता है: stackoverflow.com/questions/46087730/… । यह r8-r11 को zeros करता है, और 32-बिट प्रक्रिया में चलाने पर ठीक उसी तरह काम करता है। उस प्रश्नोत्तर में मेरे पास एक उदाहरण है जो इसे काम करते हुए दिखा रहा है, या एक सूचक को काटकर विफल कर रहा है। और मैं यह दिखाने के लिए कर्नेल स्रोत में भी खोदा हूं कि वह इस तरह से व्यवहार क्यों करता है।
पीटर कॉर्ड्स

1
@EvanCarroll: स्निपेट (उद्धृत पाठ) विशेष रूप से खंड 4.3 लिनक्स सिस्टम कॉल में लिनक्स असेंबली ट्यूटोरियल दिए गए लिंक पर है
माइकल पेटीच

14

शायद आप x86_64 ABI की तलाश कर रहे हैं?

यदि आपके बाद वह ठीक नहीं है, तो वैकल्पिक संदर्भ खोजने के लिए अपने पसंदीदा खोज इंजन में 'x86_64 अबी' का उपयोग करें।


5
वास्तव में, मैं केवल सिस्टम कॉल सम्मेलन चाहता हूं। UNIX (FreeBSD) के लिए esp
पंजे

3
@claws: सिस्टम कॉल कन्वेंशन ABI का एक हिस्सा है।
जोनाथन लेफ़लर

1
हाँ। मैं प्रत्येक व्यक्ति के ओएस के कर्नेल विकास के पास गया हूं और उनसे इसके बारे में पूछा। उन्होंने मुझे स्रोत में देखने और पता लगाने के लिए कहा है। मुझे सामान के दस्तावेज के बिना समझ में नहीं आता कि वे सिर्फ विकास कैसे शुरू कर सकते हैं? इसलिए, मैंने अपने द्वारा एकत्रित जानकारी से एक उत्तर जोड़ा है, जिससे दूसरों को बाकी विवरण भरने की उम्मीद है।
पंजे

@JonathanLeffler लिंक अभी काम नहीं कर रहा है। यदि आपको लिंक पर जाकर कोई समस्या आ रही है, तो क्या आप इसे अपडेट कर सकते हैं?
अजय ब्रह्मक्षत्रिय

@AjayBrahmakshatriya: सिर ऊपर करने के लिए धन्यवाद; मैंने वेबैक मशीन रिकॉर्ड के लिए एक लिंक जोड़ा है। संपूर्ण x86-64.org वेब साइट ने किसी भी डेटा का जवाब नहीं दिया।
जोनाथन लेफ़लर

11

कॉलिंग कन्वेंशन यह परिभाषित करता है कि कॉल करने या अन्य प्रोग्राम द्वारा कॉल किए जाने पर रजिस्टरों में पैरामीटर कैसे पारित किए जाते हैं। और इन सम्मेलन का सबसे अच्छा स्रोत प्रत्येक हार्डवेयर के लिए परिभाषित ABI मानकों के रूप में है। संकलन में आसानी के लिए, उसी ABI का उपयोग यूजरस्पेस और कर्नेल प्रोग्राम द्वारा भी किया जाता है। Linux / Freebsd x86-64 के लिए समान ABI और 32-बिट के लिए एक और सेट का अनुसरण करता है। लेकिन विंडोज के लिए x86-64 ABI लिनक्स / फ्रीबीएसडी से अलग है। और आम तौर पर एबीआई सिस्टम कॉल को सामान्य "फ़ंक्शन कॉल" बनाम अंतर नहीं करता है। यानी, यहाँ x86_64 कॉलिंग कन्वेंशन का एक विशेष उदाहरण है और यह लिनक्स यूजरस्पेस और कर्नेल दोनों के लिए समान है: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64 ( / अनुक्रम a, b, c, d, e, f का मानदंड नोट करें):

कॉलिंग सम्मेलनों बनाम रजिस्टरों के उपयोग का एक अच्छा प्रतिपादन

प्रदर्शन इन ABI के कारणों में से एक है (उदाहरण के लिए, मेमोरी स्टैक्स में बचत के बजाय रजिस्टरों के माध्यम से पैरामीटर पारित करना)

एआरएम के लिए विभिन्न ABI है:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference.pdf

ARM64 सम्मेलन:

http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf

PowerPC पर लिनक्स के लिए:

http://refspecs.freestandards.org/elf/elfspec_ppc.pdf

http://www.0x04.net/doc/elf/psABI-ppc64.pdf

और एम्बेडेड के लिए PPC EABI है:

http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf

यह दस्तावेज़ सभी विभिन्न सम्मेलनों का अच्छा अवलोकन है:

http://www.agner.org/optimize/calling_conventions.pdf


पूरी तरह से बिंदु के अलावा। प्रश्न का पोस्टर 64 बिट syscall के लिए लिनक्स में सम्मेलन बुलाने के लिए नहीं पूछेगा यदि यह सामान्य ABI रूपांतरणों से समान था।
अल्बर्ट वैन डेर होर्स्ट

6

लिनक्स कर्नेल 5.0 स्रोत टिप्पणियाँ

मुझे पता था कि x86 बारीकियों के तहत हैं arch/x86, और syscall सामान के तहत चला जाता है arch/x86/entry। तो git grep rdiउस निर्देशिका में एक त्वरित मुझे आर्क / x86 / प्रविष्टि / प्रविष्टि_64.S की ओर ले जाता है :

/*
 * 64-bit SYSCALL instruction entry. Up to 6 arguments in registers.
 *
 * This is the only entry point used for 64-bit system calls.  The
 * hardware interface is reasonably well designed and the register to
 * argument mapping Linux uses fits well with the registers that are
 * available when SYSCALL is used.
 *
 * SYSCALL instructions can be found inlined in libc implementations as
 * well as some other programs and libraries.  There are also a handful
 * of SYSCALL instructions in the vDSO used, for example, as a
 * clock_gettimeofday fallback.
 *
 * 64-bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
 * then loads new ss, cs, and rip from previously programmed MSRs.
 * rflags gets masked by a value from another MSR (so CLD and CLAC
 * are not needed). SYSCALL does not save anything on the stack
 * and does not change rsp.
 *
 * Registers on entry:
 * rax  system call number
 * rcx  return address
 * r11  saved rflags (note: r11 is callee-clobbered register in C ABI)
 * rdi  arg0
 * rsi  arg1
 * rdx  arg2
 * r10  arg3 (needs to be moved to rcx to conform to C ABI)
 * r8   arg4
 * r9   arg5
 * (note: r12-r15, rbp, rbx are callee-preserved in C ABI)
 *
 * Only called from user space.
 *
 * When user can change pt_regs->foo always force IRET. That is because
 * it deals with uncanonical addresses better. SYSRET has trouble
 * with them due to bugs in both AMD and Intel CPUs.
 */

और आर्क / x86 / प्रविष्टि / प्रविष्टि_32.S पर 32-बिट के लिए :

/*
 * 32-bit SYSENTER entry.
 *
 * 32-bit system calls through the vDSO's __kernel_vsyscall enter here
 * if X86_FEATURE_SEP is available.  This is the preferred system call
 * entry on 32-bit systems.
 *
 * The SYSENTER instruction, in principle, should *only* occur in the
 * vDSO.  In practice, a small number of Android devices were shipped
 * with a copy of Bionic that inlined a SYSENTER instruction.  This
 * never happened in any of Google's Bionic versions -- it only happened
 * in a narrow range of Intel-provided versions.
 *
 * SYSENTER loads SS, ESP, CS, and EIP from previously programmed MSRs.
 * IF and VM in RFLAGS are cleared (IOW: interrupts are off).
 * SYSENTER does not save anything on the stack,
 * and does not save old EIP (!!!), ESP, or EFLAGS.
 *
 * To avoid losing track of EFLAGS.VM (and thus potentially corrupting
 * user and/or vm86 state), we explicitly disable the SYSENTER
 * instruction in vm86 mode by reprogramming the MSRs.
 *
 * Arguments:
 * eax  system call number
 * ebx  arg1
 * ecx  arg2
 * edx  arg3
 * esi  arg4
 * edi  arg5
 * ebp  user stack
 * 0(%ebp) arg6
 */

glibc 2.29 लिनक्स x86_64 सिस्टम कॉल कार्यान्वयन

अब एक प्रमुख libc कार्यान्वयन को देखते हुए धोखा देते हैं और देखते हैं कि वे क्या कर रहे हैं।

ग्लिब को देखने से बेहतर क्या हो सकता है कि मैं इस उत्तर को लिखते समय अभी उपयोग कर रहा हूं? :-)

glibc 2.29 x86_64 syscalls को परिभाषित करता है sysdeps/unix/sysv/linux/x86_64/sysdep.hऔर जिसमें कुछ दिलचस्प कोड होते हैं, जैसे:

/* The Linux/x86-64 kernel expects the system call parameters in
   registers according to the following table:

    syscall number  rax
    arg 1       rdi
    arg 2       rsi
    arg 3       rdx
    arg 4       r10
    arg 5       r8
    arg 6       r9

    The Linux kernel uses and destroys internally these registers:
    return address from
    syscall     rcx
    eflags from syscall r11

    Normal function call, including calls to the system call stub
    functions in the libc, get the first six parameters passed in
    registers and the seventh parameter and later on the stack.  The
    register use is as follows:

     system call number in the DO_CALL macro
     arg 1      rdi
     arg 2      rsi
     arg 3      rdx
     arg 4      rcx
     arg 5      r8
     arg 6      r9

    We have to take care that the stack is aligned to 16 bytes.  When
    called the stack is not aligned since the return address has just
    been pushed.


    Syscalls of more than 6 arguments are not supported.  */

तथा:

/* Registers clobbered by syscall.  */
# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"

#undef internal_syscall6
#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \
({                                  \
    unsigned long int resultvar;                    \
    TYPEFY (arg6, __arg6) = ARGIFY (arg6);              \
    TYPEFY (arg5, __arg5) = ARGIFY (arg5);              \
    TYPEFY (arg4, __arg4) = ARGIFY (arg4);              \
    TYPEFY (arg3, __arg3) = ARGIFY (arg3);              \
    TYPEFY (arg2, __arg2) = ARGIFY (arg2);              \
    TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \
    register TYPEFY (arg6, _a6) asm ("r9") = __arg6;            \
    register TYPEFY (arg5, _a5) asm ("r8") = __arg5;            \
    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;           \
    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;           \
    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;           \
    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \
    asm volatile (                          \
    "syscall\n\t"                           \
    : "=a" (resultvar)                          \
    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),     \
      "r" (_a5), "r" (_a6)                      \
    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \
    (long int) resultvar;                       \
})

जो मुझे लगता है कि बहुत आत्म व्याख्यात्मक हैं। ध्यान दें कि यह कैसे लगता है कि इसे नियमित रूप से सिस्टम V AMD64 ABI फ़ंक्शन के कॉलिंग कन्वेंशन से मेल खाने के लिए डिज़ाइन किया गया है: https://en.wikipedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions

क्लोबर्स का त्वरित अनुस्मारक:

  • ccका अर्थ है झंडा रजिस्टर। लेकिन पीटर कॉर्डेस की टिप्पणी है कि यह यहाँ अनावश्यक है।
  • memory इसका मतलब है कि एक पॉइंटर को असेंबली में पास किया जा सकता है और इसका उपयोग मेमोरी तक पहुंचने के लिए किया जा सकता है

खरोंच से एक स्पष्ट न्यूनतम रननीय उदाहरण के लिए यह उत्तर देखें: इनलाइन असेंबली में सिसेंटर के माध्यम से एक सिस्टम कॉल कैसे आमंत्रित करें?

मैन्युअल रूप से विधानसभा में कुछ syscalls करें

बहुत वैज्ञानिक नहीं, लेकिन मजेदार:

  • x86_64.S

    .text
    .global _start
    _start:
    asm_main_after_prologue:
        /* write */
        mov $1, %rax    /* syscall number */
        mov $1, %rdi    /* stdout */
        mov $msg, %rsi  /* buffer */
        mov $len, %rdx  /* len */
        syscall
    
        /* exit */
        mov $60, %rax   /* syscall number */
        mov $0, %rdi    /* exit status */
        syscall
    msg:
        .ascii "hello\n"
    len = . - msg
    

    गिटहब ऊपर

aarch64

मैंने यहां एक न्यूनतम रन करने योग्य उपयोगकर्ताभूमि उदाहरण दिखाया है: /reverseengineering/16917/arm64-syscalls-table/18834#18834 TODO grep khr कोड यहाँ आसान होना चाहिए।


1
"cc"मार-पीट अनावश्यक है: लिनक्स syscalls बचाने / RFLAGS बहाल ( syscall/ sysretअनुदेशों R11 उपयोग कर, और गिरी बचाया R11 संशोधित नहीं करता है / के माध्यम से के अलावा अन्य RFLAGS कर ptraceडिबगर सिस्टम कॉल।) ऐसा नहीं है कि यह कभी मायने रखती है, क्योंकि एक "cc"पीटना है ग्नू सी एक्सटेंडेड एक्सएमआई में x86 / x86-64 के लिए निहित है, इसलिए आप इसे छोड़कर कुछ भी हासिल नहीं कर सकते।
पीटर कॉर्डेस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.