मुझे लगता है कि अपने कोड ठीक चल रहा है, और अंत में मुसीबत में हो रही: क्या आप a++
के बाद होने की उम्मीद करते हैं?
mymain()
केवल एक सामान्य सी फ़ंक्शन है, जो इसके कॉलर पर वापस आने का प्रयास करेगा।
लेकिन आपने इसे ईएलएफ एंट्री पॉइंट के रूप में सेट किया है, जो ईएलएफ लोडर को सही जगह पर प्रोग्राम सेगमेंट लोड करने के बाद इसे कूदने के लिए कहता है - और यह आपको वापस आने की उम्मीद नहीं करता है।
उन "अन्य ऑब्जेक्ट फ़ाइलें जैसे crt1.o
, crti.o
और crtn.o
" आमतौर पर सी प्रोग्राम के लिए इस सामग्री को संभालते हैं। एक सी प्रोग्राम के लिए ईएलएफ एंट्री पॉइंट main()
नहीं है - इसके बजाए, यह एक रैपर है जो main()
(उदाहरण के लिए argc
और argv
प्लेटफॉर्म के आधार पर स्टैक या रजिस्टरों पर तर्क) को सेट करने के लिए उचित वातावरण स्थापित करता है, main()
पर कॉल करता है (उम्मीद है कि यह वापस आ सकता है), और उसके बाद exit
सिस्टम कॉल (main()
से वापसी कोड के साथ) को आमंत्रित करता है।
[अपडेट निम्नलिखित टिप्पणियां:]
जब मैं gdb
के साथ अपने उदाहरण का प्रयास करें, मुझे लगता है कि यह वास्तव में mymain()
से लौटने पर विफल करता है: mymain
पर एक ब्रेकपाइंट सेट करने के बाद, और फिर के माध्यम से कदम निर्देश, मुझे लगता है कि यह वेतन वृद्धि करता है, तो समारोह उपसंहार में मुसीबत में हो जाता है:
$ gcc -g -c main.c
$ ld -o prog -T my_script.lds main.o
$ gdb ./prog
...
(gdb) b mymain
Breakpoint 1 at 0x10006: file main.c, line 4.
(gdb) r
Starting program: /tmp/prog
Breakpoint 1, mymain() at main.c:4
4 a++;
(gdb) display/i $pc
1: x/i $pc
0x10006 <mymain+6>: addl $0x1,-0x4(%ebp)
(gdb) si
5 }
1: x/i $pc
0x1000a <mymain+10>: leave
(gdb) si
Cannot access memory at address 0x4
(gdb) si
0x00000001 in ??()
1: x/i $pc
Disabling display 1 to avoid infinite recursion.
0x1: Cannot access memory at address 0x1
(gdb) q
कम से कम i386 के लिए, ईएलएफ लोडर लोड कोड दर्ज करने से पहले एक समझदार ढेर सेट करता है, इसलिए आप ई सीएफ प्रविष्टि बिंदु को सी फ़ंक्शन पर सेट कर सकते हैं और उचित व्यवहार प्राप्त कर सकते हैं; हालांकि, जैसा कि मैंने उपरोक्त उल्लेख किया है, आपको एक स्वच्छ प्रक्रिया को स्वयं से बाहर निकलना होगा। और यदि आप सी रनटाइम का उपयोग नहीं कर रहे हैं, तो आप बेहतर ढंग से सी रनटाइम पर निर्भर किसी भी पुस्तकालय का उपयोग नहीं करेंगे।
तो यहाँ इस बात का एक उदाहरण है, अपने मूल लिंकर स्क्रिप्ट का उपयोग कर - के रूप में a
के अंतिम मूल्य के साथ लेकिन सी कोड ज्ञात मान को a
आरंभ, और एक exit
सिस्टम कॉल आह्वान करने के लिए संशोधित साथ (इनलाइन विधानसभा का प्रयोग करके) निकास कोड। (नोट: मुझे अभी एहसास हुआ है कि आपने बिल्कुल नहीं कहा है कि आप किस प्लेटफॉर्म का उपयोग कर रहे हैं; मैं यहां लिनक्स मान रहा हूं।)
$ cat main2.c
void mymain(void)
{
int a = 42;
a++;
asm volatile("mov $1,%%eax; mov %0,%%ebx; int $0x80" : : "r"(a) : "%eax");
}
$ gcc -c main2.c
$ ld -o prog2 -T my_script.lds main2.o
$ ./prog2 ; echo $?
43
$
धन्यवाद यूथर्स के लिए मैथ्यू। मैं कहता हूं कि प्रोग्राम स्टार्टअप पर दुर्घटनाग्रस्त हो जाता है क्योंकि gdb यह कहता है ... मुझे पता है कि 'मुख्य' से पहले अन्य फ़ंक्शन कहा जाता है, उदाहरण के लिए ctors मुझे लगता है। लेकिन अगर मैं 'मुख्य' के लिए दूसरा नाम कहूं तो मुझे इसे निर्दिष्ट करना चाहिए? और, यदि मैं अपने प्रोग्राम को 'ld' के साथ स्पष्ट रूप से लिंक करता हूं तो क्या मुझे सी रनटाइम ऑब्जेक्ट फ़ाइलों को भी पास करना होगा? – MirkoBanchi
आप क्या हासिल करने की कोशिश कर रहे हैं? क्या आप सामान्य सी रनटाइम और पुस्तकालयों का उपयोग करना चाहते हैं? यदि ऐसा है, तो आपके मुख्य फ़ंक्शन को 'मुख्य' कहा जाना चाहिए: सी रनटाइम कॉल यही है। (यह ईएलएफ एंट्री पॉइंट जैसा ही नहीं है, जो आमतौर पर 'crt1.o' में '_start' है।) यदि आप सीधे' ld' का आह्वान कर रहे हैं, तो हाँ, आपको विभिन्न सी रनटाइम फ़ाइलों को स्वयं लिंक करना होगा। यदि आप 'gcc' का उपयोग कर रहे हैं, तो यह आपके लिए ऐसा करेगा। आप देख सकते हैं कि यह 'gcc -v' के साथ क्या करता है, लेकिन आपको यह जानना होगा कि यह एक रैपर के माध्यम से 'ld' को आमंत्रित करता है,' collect2' (देखें [यहां] (http://gcc.gnu.org/onlinedocs/gcc -4.6.1/gccint/Collect2.html))। –
मुझे पता होगा कि संभव है कि एक निष्पादन योग्य (ईएलएफ प्रारूप) बनाएं जो सी रनटाइम ऑब्जेक्ट फ़ाइलों को लिंक किए बिना सही ढंग से चलता है। – MirkoBanchi