मैंने आपके लिए यह दिखाने के लिए अलग-अलग हिस्सों को तोड़ दिया है कि सी स्रोत से असेंबली कैसे बनाई गई थी।
8(%ebp)
= x
, 12(%ebp)
= y
, 16(%ebp)
= z
arith:
स्टैक फ्रेम बनाएँ:
pushl %ebp
movl %esp,%ebp
ले जाएँ
x
eax
में,
y
edx
में:
movl 8(%ebp),%eax
movl 12(%ebp),%edx
t1 = x + y
।
leal
(लोड प्रभावी पता)
edx
और
eax
, और
t1
जोड़ देगा
ecx
में होगा:
leal (%edx,%eax),%ecx
int t4 = y * 48;
नीचे दो चरणों में, 3 से गुणा करें, तो 16 से
t4
अंततः
edx
में होगा :
edx
गुणा करके 2, और परिणाम के लिए edx
जोड़ें, यानी। edx = edx * 3
:
leal (%edx,%edx,2),%edx
शिफ्ट 4 बिट्स, यानी छोड़ दिया गया। 16 से गुणा करें:
sall $4,%edx
int t2 = z+t1;
।
ecx
शुरू में
t1
रखती है,
z
,
16(%ebp)
पर है अनुदेश
ecx
के अंत में
t2
लेंगे:
addl 16(%ebp),%ecx
int t5 = t3 + t4;
।
t3
बस
x + 4
था, और
t3
की गणना और भंडारण के बजाय,
t3
की अभिव्यक्ति इनलाइन रखी गई है। यह निर्देश आवश्यक है
(x+4) + t4
, जो
t3
+
t4
जैसा ही है। यह
edx
(
t4
) और
eax
(
x
) जोड़ता है, और उस परिणाम को प्राप्त करने के लिए
ऑफसेट के रूप में 4 जोड़ता है।
leal 4(%edx,%eax),%eax
int rval = t2 * t5;
काफी इस सीधी-सपाट एक; ecx
t2
और eax
का प्रतिनिधित्व करता है t5
का प्रतिनिधित्व करता है। वापसी मूल्य eax
के माध्यम से कॉलर को वापस भेज दिया जाता है।
imull %ecx,%eax
स्टैक फ्रेम को नष्ट और
esp
और
ebp
बहाल: दिनचर्या से
movl %ebp,%esp
popl %ebp
वापसी:
ret
इस उदाहरण से आप देख सकते हैं कि रेसुल टी एक जैसा है, लेकिन संरचना थोड़ा अलग है। सबसे अधिक संभावना है कि इस कोड को किसी प्रकार के अनुकूलन के साथ संकलित किया गया था या किसी ने इसे स्वयं को एक बिंदु प्रदर्शित करने के लिए लिखा था।
जैसा कि अन्य ने कहा है, आप पूरी तरह से अलग-अलग हिस्सों से स्रोत पर नहीं जा सकते हैं। समकक्ष सी कोड के साथ आने के लिए असेंबली पढ़ने वाले व्यक्ति की व्याख्या पर निर्भर है।
gcc -c -g arith.c
:
डिबग जानकारी (
-g
) है, जो स्रोत एम्बेड कर देंगे साथ
संकलित:
सीखने विधानसभा और अपने सी कार्यक्रमों के disassembly को समझने के साथ मदद करने के लिए आप लिनक्स पर निम्न कर सकते हैं
यदि आप 64-बिट मशीन पर हैं, तो आप -m32
ध्वज के साथ 32-बिट बाइनरी बनाने के लिए कंपाइलर को बता सकते हैं (मैंने नीचे दिए गए उदाहरण के लिए ऐसा किया था)।
उपयोग objdump वस्तु फ़ाइल डंप करने के लिए यह स्रोत interleaved के साथ:
objdump -d -S arith.o
-d
= disassembly, -S
= प्रदर्शन स्रोत। यदि आप एटी & टी सिंटैक्स पर अपना उदाहरण उपयोग करते हैं तो आप इंटेल एएसएम सिंटैक्स का उपयोग करने के लिए -M intel-mnemonic
जोड़ सकते हैं।
आउटपुट:
arith.o: file format elf32-i386
Disassembly of section .text:
00000000 <arith>:
int arith(int x, int y, int z)
{
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 20 sub $0x20,%esp
int t1 = x+y;
6: 8b 45 0c mov 0xc(%ebp),%eax
9: 8b 55 08 mov 0x8(%ebp),%edx
c: 01 d0 add %edx,%eax
e: 89 45 fc mov %eax,-0x4(%ebp)
int t2 = z+t1;
11: 8b 45 fc mov -0x4(%ebp),%eax
14: 8b 55 10 mov 0x10(%ebp),%edx
17: 01 d0 add %edx,%eax
19: 89 45 f8 mov %eax,-0x8(%ebp)
int t3 = x+4;
1c: 8b 45 08 mov 0x8(%ebp),%eax
1f: 83 c0 04 add $0x4,%eax
22: 89 45 f4 mov %eax,-0xc(%ebp)
int t4 = y * 48;
25: 8b 55 0c mov 0xc(%ebp),%edx
28: 89 d0 mov %edx,%eax
2a: 01 c0 add %eax,%eax
2c: 01 d0 add %edx,%eax
2e: c1 e0 04 shl $0x4,%eax
31: 89 45 f0 mov %eax,-0x10(%ebp)
int t5 = t3 + t4;
34: 8b 45 f0 mov -0x10(%ebp),%eax
37: 8b 55 f4 mov -0xc(%ebp),%edx
3a: 01 d0 add %edx,%eax
3c: 89 45 ec mov %eax,-0x14(%ebp)
int rval = t2 * t5;
3f: 8b 45 f8 mov -0x8(%ebp),%eax
42: 0f af 45 ec imul -0x14(%ebp),%eax
46: 89 45 e8 mov %eax,-0x18(%ebp)
return rval;
49: 8b 45 e8 mov -0x18(%ebp),%eax
}
4c: c9 leave
4d: c3 ret
आप देख सकते हैं, अनुकूलन के बिना संकलक उदाहरण आपके पास तुलना में एक बड़ा बाइनरी पैदा करता है। आप इसके साथ खेल सकते हैं और संकलन करते समय एक कंपाइलर अनुकूलन ध्वज जोड़ सकते हैं (यानी -O1
, -O2
, -O3
)। ऑप्टिमाइज़ेशन स्तर जितना ऊंचा होगा, उतना ही अमूर्त प्रतीत होता है।
उदाहरण के लिए, बस स्तर 1 अनुकूलन (gcc -c -g -O1 -m32 arith.c1
), उत्पादन विधानसभा कोड के साथ एक बहुत कम है:
00000000 <arith>:
int arith(int x, int y, int z)
{
0: 8b 4c 24 04 mov 0x4(%esp),%ecx
4: 8b 54 24 08 mov 0x8(%esp),%edx
int t1 = x+y;
8: 8d 04 11 lea (%ecx,%edx,1),%eax
int t2 = z+t1;
b: 03 44 24 0c add 0xc(%esp),%eax
int t3 = x+4;
int t4 = y * 48;
f: 8d 14 52 lea (%edx,%edx,2),%edx
12: c1 e2 04 shl $0x4,%edx
int t5 = t3 + t4;
15: 8d 54 11 04 lea 0x4(%ecx,%edx,1),%edx
int rval = t2 * t5;
19: 0f af c2 imul %edx,%eax
return rval;
}
1c: c3 ret
क्या अनुकूलन स्तर आप उपयोग कर रहे हैं जब आप संकलन कर रहे हैं? यदि आप लाइन-दर-लाइन रूपांतरण चाहते हैं, तो -00 का उपयोग करें, अन्यथा, आपको अनुकूलन को ध्यान में रखना होगा। – Maz
... और मूल सी कथन आदेश पर अनुकूलित कोड को वापस करने का पूरी तरह से संभव नहीं है। –
क्या आप वाकई एक बेवकूफ संकलन है? ऐसा लगता है कि यह कुछ हद तक अनुकूलित है। बीजगणितीय अभिव्यक्ति लिखें कि फ़ंक्शन गणना करता है और देखता है कि क्या आप इसे खोज सकते हैं। –