आप शायद सामान्य कॉलिंग सम्मेलन (ढेर पर तर्क) सोच रहे हैं। आधुनिक लिनक्स कर्नेल (32-बिट संस्करण) रजिस्टरों में पहले 3 पैरामीटर (ईएक्स, ईसीएक्स, EDX) ऑप्टिमाइज़ेशन के रूप में पास करते हैं। कर्नेल के आधार पर इस सम्मेलन को __attribute__(regparm(3))
का उपयोग करके फ़ंक्शंस पर एक विशेषता संशोधक के रूप में निर्दिष्ट किया गया है, या कमांड लाइन पर GCC पर कर्नेल पास -mregparm=3
विकल्प का वैकल्पिक संस्करण। जीसीसीdocumentation कि विकल्प/विशेषता के बारे में इस का कहना है:
regparm (number)
On the Intel 386, the regparm attribute causes the compiler to pass up to
number integer arguments in registers EAX, EDX, and ECX instead of on the
stack. Functions that take a variable number of arguments will continue to
be passed all of their arguments on the stack.
प्राचीन कर्नेल में सामान्य 32-बिट ABI (और स्टैक पर बहस के सम्मेलन) के आदर्श था।
config REGPARM
bool "Use register arguments"
default y
help
Compile the kernel with -mregparm=3. This instructs gcc to use
a more efficient function call ABI which passes the first three
arguments of a function call via registers, which results in denser
and faster code.
If this option is disabled, then the default ABI of passing
arguments via the stack is used.
If unsure, say Y.
लिनक्स कर्नेल देखरेख के साथ 2006 में इस विकल्प से छुटकारा मिला: रजिस्टरों या गिरी निर्माण विन्यास में CONFIG_REGPARM सेटिंग के माध्यम से सामान्य ढेर सम्मेलन में आखिरकार गिरी विन्यास समर्थित तर्क इस kernel commit:
-mregparm=3 has been enabled by default for some time on i386, and AFAIK
there aren't any problems with it left.
This patch removes the REGPARM config option and sets -mregparm=3
unconditionally.
इस ज्ञान के आधार पर कोई आपके द्वारा प्रस्तुत किए गए कोड को देख सकता है और मान लें कि हम कर्नेल पर हैं जहां यह रजिस्टरों में पारित होने वाले पहले 3 पैरामीटर में डिफॉल्ट हो गया है।आपके मामले में:
__visible void __irq_entry smp_apic_timer_interrupt(struct pt_regs *regs)
तो यह EAX में पारित हो जाता है एक पैरामीटर है। कोड है कि smp_apic_timer_interrupt कहा जाता है इस तरह देखा:
ENTRY(apic_timer_interrupt)
RING0_INT_FRAME;
ASM_CLAC;
pushl_cfi $~(0xef);
SAVE_ALL;
TRACE_IRQS_OFF
movl %esp,%eax;
call smp_apic_timer_interrupt; // <------call high level C function
jmp ret_from_intr;
CFI_ENDPROC;
ENDPROC(apic_timer_interrupt)
महत्वपूर्ण बात यह है कि SAVE_ALL मैक्रो कॉल स्टैक पर सभी आवश्यक रजिस्टरों धक्का है। यह संस्करण से गिरी के संस्करण के लिए अलग अलग होंगे, लेकिन ढेर पर रजिस्टरों धकेलने का मुख्य प्रभाव समान है (मैं संक्षिप्तता के लिए बौना प्रविष्टियों को हटा दिया है):
.macro SAVE_ALL
cld
PUSH_GS
pushl_cfi %fs
pushl_cfi %es
pushl_cfi %ds
pushl_cfi %eax
pushl_cfi %ebp
pushl_cfi %edi
pushl_cfi %esi
pushl_cfi %edx
pushl_cfi %ecx
pushl_cfi %ebx
movl $(__USER_DS), %edx
movl %edx, %ds
movl %edx, %es
movl $(__KERNEL_PERCPU), %edx
movl %edx, %fs
SET_KERNEL_GS %edx
.endm
जब ईएसपी पूरा होगा उस स्थान पर इंगित करें जहां अंतिम रजिस्टर धक्का दिया गया था। उस पते को ईएक्स पर movl %esp,%eax
के साथ कॉपी किया गया है, और ईएक्सstruct pt_regs *regs
के लिए सूचक बन गया है। ढेर पर सभी धक्का रजिस्ट्रार वास्तविक pt_regs डेटा संरचना बन जाते हैं, और ईएक्स अब इसे इंगित करता है।
asmlinkage
मैक्रो उन कार्यों के लिए कर्नेल में मिलेगा जिनके लिए परंपरागत तरीके से स्टैक पर पारित होने वाले तर्कों की आवश्यकता होती है। यह कुछ इस तरह के रूप में परिभाषित किया गया है:
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
कहाँ regparm(0)
का कहना है कि कोई पैरामीटर रजिस्टर के माध्यम से पारित हो जाएगा।
एक सच में पता है कि निर्माण विकल्प हैं, और कर्नेल के संस्करण सम्मेलन का सटीक आकलन इस्तेमाल किया जा रहा बनाने के लिए इस्तेमाल किया जा रहा।
स्रोत लगता है कि यह है, जहां वे ढेर पर संग्रहीत कर रहे हैं करने के लिए एक सूचक चाहता है तो 'eax' समझ में आता है, लेकिन न तो सवाल और न ही उत्तर लिनक्स (कर्नेल) के बारे में कुछ भी कहा है आंतरिक रूप से एक रजिस्टर-कॉल फ़ंक्शन का उपयोग I386 के लिए भी एबीआई (amd64 नहीं)। मान लें कि आप 'mov% esp,% eax' क्यों है, यह एक बेहतर जवाब होगा यदि आप उस कर्नेल दस्तावेज़ों से लिंक कर सकते हैं जो इसे समझाते हैं। अन्यथा मैं मानता हूं कि 'smp_apic_timer_interrupt' आखिरी चीज को स्टैक ('% ebx') पर अपने पहले तर्क के रूप में धक्का देगी, जो समझ में नहीं आता है। –
लिनक्स कर्नेल फास्टकॉल (ईएक्स, एक्क्स, एडएक्स) बनाया गया है। –