2009-12-21 16 views
26

वहाँ किसी भी पर्याप्त अनुकूलन जब फ्रेम सूचक को छोड़ते हुए है? मैं this पेज पढ़कर सही ढंग से समझ लिया है, तो प्रयोग किया जाता है जब हम बचत से बचना चाहते हैं, की स्थापना और फ्रेम संकेत बहाल।मुझे फ्रेम सूचक को कब छोड़ना चाहिए?

क्या यह केवल प्रत्येक फ़ंक्शन कॉल के लिए किया जाता है और यदि ऐसा है, तो क्या यह वास्तव में प्रत्येक फ़ंक्शन के लिए कुछ निर्देशों से बचने के लायक है? एक अनुकूलन के लिए तुच्छ है ना। डिबगिंग सीमाओं से अलग इस विकल्प का उपयोग की वास्तविक निहितार्थ क्या हैं?

मैं,

# gcc -S -fomit-frame-pointer code.c -o withoutfp.s 
# gcc -S code.c -o withfp.s 

साथ और इस विकल्प

int main(void) 
{ 
     int i; 

     i = myf(1, 2); 
} 

int myf(int a, int b) 
{ 
     return a + b; 
} 

बिना निम्नलिखित सी कोड संकलित।


--- withfp.s 2009-12-22 00:03:59.000000000 +0000 
+++ withoutfp.s 2009-12-22 00:04:17.000000000 +0000 
@@ -7,17 +7,14 @@ 
     leal 4(%esp), %ecx 
     andl $-16, %esp 
     pushl -4(%ecx) 
-  pushl %ebp 
-  movl %esp, %ebp 
     pushl %ecx 
-  subl $36, %esp 
+  subl $24, %esp 
     movl $2, 4(%esp) 
     movl $1, (%esp) 
     call myf 
-  movl %eax, -8(%ebp) 
-  addl $36, %esp 
+  movl %eax, 20(%esp) 
+  addl $24, %esp 
     popl %ecx 
-  popl %ebp 
     leal -4(%ecx), %esp 
     ret 
     .size main, .-main 
@@ -25,11 +22,8 @@ 
.globl myf 
     .type myf, @function 
myf: 
-  pushl %ebp 
-  movl %esp, %ebp 
-  movl 12(%ebp), %eax 
-  addl 8(%ebp), %eax 
-  popl %ebp 
+  movl 8(%esp), %eax 
+  addl 4(%esp), %eax 
     ret 
     .size myf, .-myf 
     .ident "GCC: (GNU) 4.2.1 20070719 

किसी उपरोक्त कोड जहां -fomit फ्रेम-सूचक वास्तव में फर्क था की कुंजी बिंदुओं पर प्रकाश डाला कृपया सकते हैं:

diff -u 'दो फ़ाइलों ing निम्नलिखित विधानसभा कोड का पता चला ?

संपादित करें:objdump के उत्पादन gcc -S के साथ बदल दिया है

+2

-एस के साथ संकलन करके फिर से अंतर का प्रयास करें। असेंबली भाषा की तुलना करें: यह बहुत अधिक पठनीय होगा। –

+0

@ रिचर्ड: हो गया! इस पर ध्यान दिलाने के लिए धन्यवाद! – PetrosB

+0

संबंधित, देखें [एआरएम: लिंक रजिस्टर और फ्रेम पॉइंटर] (http://stackoverflow.com/q/15752188)। – jww

उत्तर

24

एक अतिरिक्त रजिस्टर सामान्य प्रयोजन उपयोग के लिए उपलब्ध हो सकते हैं। मुझे लगता है कि इस वास्तव में केवल 32-बिट x86, जो थोड़ा रजिस्टरों के लिए भूखे है पर एक बड़ी बात है। *

एक ईबीपी नहीं रह गया है को बचाया और हर कार्य कॉल पर समायोजित, और शायद कुछ अतिरिक्त उपयोग देखने की अपेक्षा करेंगे जहां ईबीपी एक सामान्य प्रयोजन रजिस्टर के रूप में इस्तेमाल किया जाता है सामान्य कोड में ईबीपी, और अवसरों पर कम ढेर आपरेशन के।

आपका कोड इस तरह के अनुकूलन से कोई लाभ देखने के लिए बहुत आसान है - आप पर्याप्त रजिस्टरों का उपयोग नहीं कर रहे हैं। साथ ही, आपने ऑप्टिमाइज़र चालू नहीं किया है, जो इन प्रभावों में से कुछ को देखना आवश्यक हो सकता है।

* आईएसए रजिस्ट्रार, माइक्रो-आर्किटेक्चर रजिस्ट्रार नहीं।

+0

यदि मुझे स्पष्ट रूप से अन्य अनुकूलन विकल्प सेट करना है, तो इस विकल्प का अर्थ अलग क्यों है? आपका मुद्दा है कि मेरा कोड सरल है हालांकि मान्य लगता है! – PetrosB

+0

यह विकल्प अलग है क्योंकि यह डिबगिंग के लिए महत्वपूर्ण डाउनसाइड्स है। –

+0

यह अलग है क्योंकि इसमें अन्य चीजों के लिए कार्यात्मक प्रभाव पड़ता है, जैसे डीबगर में अपना कोड चलाना, या अन्य कोड से लिंक करना। मुझे लगता है कि आप ऑप्टिमाइज़र बंद होने के साथ भी पंजीकरण स्पिल में कमी देखेंगे, लेकिन चूंकि मुझे यकीन नहीं है कि मैं अपने दांव पर हेजिंग कर रहा हूं। –

9

इसे छोड़ने का एकमात्र नकारात्मक पक्ष यह है कि डिबगिंग अधिक कठिन है।

प्रमुख उल्टा एक अतिरिक्त सामान्य प्रयोजन रजिस्टर जो प्रदर्शन पर एक बड़ा फर्क कर सकते हैं है कि वहाँ है। स्पष्ट रूप से यह अतिरिक्त रजिस्टर केवल तभी उपयोग किया जाता है जब आवश्यक हो (संभवतः आपके बहुत ही सरल कार्य में यह नहीं है); कुछ कार्यों में यह दूसरों की तुलना में अधिक अंतर बनाता है।

+1

न केवल यह अधिक डफिकल्ट डीबगिंग करता है। जीएनयू डॉकसनलाइन का कहना है कि यह असंभव – PetrosB

+16

डीबगिंग करता है वे गलत हैं। 'printf()' डीबगिंग (जो ** आईएस ** अभी भी डिबगिंग) बहुत संभव है, उदाहरण के लिए। –

+8

आप अभी भी किसी भी संकलक विकल्प के बावजूद निर्देश (असेंबली भाषा) स्तर पर डीबग कर सकते हैं। स्रोत स्तर डीबगिंग सुनिश्चित करने के लिए उतना आसान नहीं है, लेकिन "असंभव" निश्चित रूप से गलत शब्द है। –

4

अपने कार्यक्रम प्रोफ़ाइल अगर वहाँ एक महत्वपूर्ण अंतर है देखने के लिए।

इसके बाद, अपने विकास की प्रक्रिया प्रोफ़ाइल। डिबगिंग आसान या अधिक कठिन है? आप और अधिक समय बिताने करें विकासशील या उससे कम? रूपरेखा के बिना

अनुकूलन समय और पैसे की बर्बादी कर रहे हैं।

+0

मेरी इच्छा है कि डाउनवॉटर एक स्पष्टीकरण छोड़ दें। –

7

आप अक्सर विधानसभा उत्पादन के लिए -S तर्क का उपयोग करके जीसीसी से अधिक सार्थक विधानसभा कोड प्राप्त कर सकते हैं:

$ gcc code.c -S -o withfp.s 
$ gcc code.c -S -o withoutfp.s -fomit-frame-pointer 
$ diff -u withfp.s withoutfp.s 

जीसीसी पते के बारे में परवाह नहीं करता, इसलिए हम सीधे उत्पन्न वास्तविक निर्देश तुलना कर सकते हैं। अपने पत्ती समारोह के लिए, यह देता है:

myf: 
-  pushl %ebp 
-  movl %esp, %ebp 
-  movl 12(%ebp), %eax 
-  addl 8(%ebp), %eax 
-  popl %ebp 
+  movl 8(%esp), %eax 
+  addl 4(%esp), %eax 
    ret 

जीसीसी ढेर पर फ्रेम सूचक पुश करने के लिए कोड उत्पन्न नहीं करता है, और इस तर्क स्टैक पर कार्य करने के लिए पारित कर दिया के रिश्तेदार का पता बदल जाता है।

संबंधित मुद्दे