मैं ओकैमल कॉलिंग सम्मेलन को खोजने की कोशिश कर रहा हूं ताकि मैं मैन्युअल रूप से स्टैक निशान की व्याख्या कर सकूं जो gdb पार्स नहीं कर सकता है। दुर्भाग्यवश, ऐसा लगता है कि सामान्य अवलोकनों को छोड़कर अंग्रेजी में कभी भी कुछ भी लिखा नहीं गया है। उदाहरण के लिए, लोग ब्लॉग पर टिप्पणी करेंगे कि ओकैमल रजिस्टरों में कई तर्क पारित करता है। (यदि वहां कहीं भी अंग्रेजी दस्तावेज है, तो एक लिंक की बहुत सराहना की जाएगी।)ओकैमल कॉलिंग सम्मेलन: क्या यह एक सटीक सारांश है?
तो मैं इसे ओकंप्लोप स्रोत से बाहर निकालने की कोशिश कर रहा हूं। क्या कोई इन अनुमानों की सटीकता की पुष्टि कर सकता है?
और, यदि मैं रजिस्टरों में पारित किए गए पहले दस तर्कों के बारे में सही हूं, तो क्या फ़ंक्शन कॉल में तर्कों को पुनर्प्राप्त करना आम तौर पर संभव नहीं है? सी में, तर्क अभी भी ढेर पर धकेल दिए जाएंगे, अगर मैं केवल सही फ्रेम पर वापस चला जाता हूं। ओकैमल में, ऐसा लगता है कि कॉलर अपने कॉलर्स के तर्कों को नष्ट करने के लिए स्वतंत्र हैं।
रजिस्टर आवंटन (/asmcomp/amd64/proc.ml
से) OCaml कार्यों में बुला लिए
,
- पहले 10 पूर्णांक और सूचक तर्क रजिस्टरों Rax, Rbx, RDI, RSI में पारित कर रहे हैं , rdx, rcx, r8, r9, r10 और r11
- रजिस्ट्रार xmm0 - xmm9 में पहले 10 फ़्लोटिंग-पॉइंट तर्क पारित किए गए हैं
- अतिरिक्त तर्क स्टैक पर धकेल दिए जाते हैं (बाएं सबसे पहले-इन-इन?), तैरता और ints और संकेत
- जाल सूचक (नीचे दिए गए अपवाद देखें) R14
- आवंटन सूचक (संभवतः नाबालिग ढेर इस blog post में वर्णित के रूप में पारित हो जाता है) R15
- का इन पारित हो जाता है intermixed वापसी मूल्य वापस रैक्स में पारित किया जाता है यदि यह एक पूर्णांक या सूचक है, और xmm0 में यह एक फ्लोट
- सभी रजिस्ट्रार कॉलर-सेव हैं?
सी कार्यों में बुला लिए, मानक amd64 सी सम्मेलन प्रयोग किया जाता है:
- पहले छह पूर्णांक और सूचक तर्क RDI, RSI, RDX, आरसीएस, R8, और r9 में पारित कर रहे हैं
- पहले आठ नाव तर्क xmm0 में पारित कर रहे हैं - xmm7
- अतिरिक्त तर्क ढेर
- वापसी मान वापस Rax में पारित हो जाता है या xmm0 पर धकेल दिया जाता है
- रजिस्टरों Rbx, RBP, और r12 - R15 हैं कॉल प्राप्त करने वाला-बचाने
वापसी पता (/asmcomp/amd64/emit.mlp
से)
वापसी पता पहले सूचक के साथ कॉल फ्रेम में धकेल दिया जाता है अनुसार, amd64 सी सम्मेलन। (मुझे अनुमान है कि ret
निर्देश इस लेआउट को मानता है।)
अपवाद (/asmcomp/linearize.ml
से)
कोड try (...body...) with (...handler...); (...rest...)
इस तरह linearized हो जाता है:
Lsetuptrap .body
(...handler...)
Lbranch .join
Llabel .body
Lpushtrap
(...body...)
Lpoptrap
Llabel .join
(...rest...)
और उसके बाद इस तरह विधानसभा के रूप में उत्सर्जित (दाईं ओर स्थलों):
call .body
(...handler...)
jmp .join
.body:
pushq %r14
movq %rsp, %r14
(...body...)
popq %r14
addq %rsp, 8
.join:
(...rest...)
शरीर में कहीं, एक रैखिकृत ओपोडहैजो इस सटीक असेंबली के रूप में उत्सर्जित हो जाता है:
movq %r14, %rsp
popq %r14
ret
जो वास्तव में साफ है! इस setjmp/longjmp व्यवसाय के बजाय, हम एक डमी फ्रेम बनाते हैं जिसका रिटर्न पता अपवाद हैंडलर है और जिसका एकमात्र स्थानीय पिछला ऐसा डमी फ्रेम है। /asmcomp/amd64/proc.ml
में "आरपी पॉइंटर" $ r14 को कॉल करने वाली एक टिप्पणी है, इसलिए मैं इस डमी फ्रेम को जाल फ्रेम कहूंगा। जब हम अपवाद उठाना चाहते हैं, तो हम सबसे हालिया जाल फ्रेम में स्टैक पॉइंटर सेट करते हैं, इससे पहले जाल पॉइंटर को जाल फ्रेम पर सेट करें, और उसके बाद अपवाद हैंडलर में "वापसी करें"। और मैं शर्त लगाता हूं कि अपवाद हैंडलर इस अपवाद को संभाल नहीं सकता है, यह सिर्फ इसे पुन: उत्पन्न करता है।
अपवाद% eax में है।