x86_64 एबीआई में, यदि किसी फ़ंक्शन में परिवर्तनीय तर्क हैं तो AL
(जो EAX
का हिस्सा है) से उस कार्य में तर्क रखने के लिए प्रयुक्त वेक्टर रजिस्टरों की संख्या को पकड़ने की उम्मीद है।
अपने उदाहरण में: तो एक वेक्टर रजिस्टर के लिए कोई आवश्यकता नहीं है, इसलिए AL
0 पर सेट है
printf("%d", 1);
एक पूर्णांक तर्क है।
दूसरी ओर, यदि आप करने के लिए अपने उदाहरण बदलने के लिए:
printf("%f", 1.0f);
तो फ्लोटिंग प्वाइंट शाब्दिक एक वेक्टर रजिस्टर में संग्रहीत किया जाता है और, तदनुसार, AL
1
पर सेट है:
movsd LC1(%rip), %xmm0
leaq LC0(%rip), %rdi
movl $1, %eax
call _printf
जैसी उम्मीद थी:
printf("%f %f", 1.0f, 2.0f);
कारण होगा संकलक 2
को AL
स्थापित करने के लिए के बाद से वहाँ दो फ्लोटिंग प्वाइंट तर्क हैं:
movsd LC0(%rip), %xmm0
movapd %xmm0, %xmm1
movsd LC2(%rip), %xmm0
leaq LC1(%rip), %rdi
movl $2, %eax
call _printf
अपने अन्य प्रश्न के लिए के रूप में:
puts
भी सही कॉल हालांकि यह पहले %eax
बाहर के शून्यीकरण है केवल एक सूचक लेता है। ऐसा क्यों है?
यह नहीं होना चाहिए। उदाहरण के लिए:
#include <stdio.h>
void test(void) {
puts("foo");
}
gcc -c -O0 -S
, आउटपुट के साथ संकलित जब:
pushq %rbp
movq %rsp, %rbp
leaq LC0(%rip), %rdi
call _puts
leave
ret
और %eax
बाहर ध्यान केंद्रित किया नहीं है। हालांकि, अगर आप #include <stdio.h>
को दूर फिर परिणामी विधानसभा बाहर शून्य सही puts()
कॉल करने से पहले %eax
करता है:
यह भी अपने खुद के लिए किसी भी कॉल करने से पहले होता है:
pushq %rbp
movq %rsp, %rbp
leaq LC0(%rip), %rdi
movl $0, %eax
call _puts
leave
ret
कारण आपके दूसरे प्रश्न से संबंधित है शून्य प्रो() फ़ंक्शन (यहां तक कि -O2 सेट के साथ), लेकिन शून्य शून्य proc (int param) फ़ंक्शन को कॉल करते समय शून्य नहीं किया जाता है।
यदि कंपाइलर किसी फ़ंक्शन की घोषणा नहीं देखता है तो यह इसके पैरामीटर के बारे में कोई धारणा नहीं करता है, और फ़ंक्शन वेरिएबल तर्कों को अच्छी तरह से स्वीकार कर सकता है। वही लागू होता है यदि आप एक खाली पैरामीटर सूची निर्दिष्ट करते हैं (जिसे आपको नहीं करना चाहिए, और इसे आईएसओ/आईईसी द्वारा एक अश्लील सी सुविधा के रूप में चिह्नित किया गया है)। चूंकि कंपाइलर में फ़ंक्शन पैरामीटर के बारे में पर्याप्त जानकारी नहीं है, इसलिए यह फ़ंक्शन को कॉल करने से पहले %eax
निकाल देता है क्योंकि यह ऐसा हो सकता है कि फ़ंक्शन को वेरिएबल तर्क के रूप में परिभाषित किया गया हो।
उदाहरण के लिए:
#include <stdio.h>
void function() {
puts("foo");
}
void test(void) {
function();
}
जहां function()
एक खाली पैरामीटर सूची है, में परिणाम:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
call _function
leave
ret
हालांकि, अगर आप void
निर्दिष्ट करने के अभ्यास की सिफारिश जब समारोह कोई पैरामीटर स्वीकार का पालन करें, जैसे:
#include <stdio.h>
void function(void) {
puts("foo");
}
void test(void) {
function();
}
n संकलक जानता है कि function()
तर्क को स्वीकार नहीं करता - विशेष रूप से, यह चर तर्क को स्वीकार नहीं करता - और इसलिए है कि समारोह कॉल करने से पहले स्पष्ट %eax
नहीं करता है:
pushq %rbp
movq %rsp, %rbp
call _function
leave
ret
'puts' भी बाहर के शून्यीकरण है'% कॉल से ठीक पहले eax 'हालांकि यह केवल एक सूचक लेता है। ऐसा क्यों है? – sh54
यह मेरे स्वयं के 'शून्य प्रो()' फ़ंक्शन (यहां तक कि -O2 सेट के साथ) के किसी भी कॉल से पहले भी होता है, लेकिन 'शून्य proc2 (int param)' फ़ंक्शन को कॉल करते समय इसे शून्य नहीं किया जाता है। – sh54
रिकॉर्ड के लिए, यह 'void proc()' पर कॉल करने से पहले होता है क्योंकि सी में यह हस्ताक्षर वास्तव में प्रो की धैर्य के बारे में कुछ भी नहीं कहता है, और यह एक भिन्न कार्य भी हो सकता है, इसलिए शून्य रैक्स आवश्यक है। 'शून्य प्रो()' 'शून्य प्रो (शून्य) 'से अलग है। एबीआई से http://stackoverflow.com/questions/693788/c-void-arguments – frangio