2012-01-25 13 views
10

मैंने किसी चीज़ फ़ाइल disassembled (सबसे अधिक संभावना विज़ुअल सी ++ संकलक उपयोग करते हुए उत्पन्न) DumpBin का उपयोग करने और कोड का निम्न भाग देखा:संकलक इस कोड को उत्पन्न क्यों करता है?

...   ... 
mov   dword ptr [ebp-4],eax  // Why save EAX? 
push  dword ptr [ebp+14h] 
push  dword ptr [ebp+10h] 
push  dword ptr [ebp+0Ch] 
push  dword ptr [ebp+8] 
mov   eax,dword ptr [ebp-4]  // Why restore EAX? Did it change at all? 
call  <function> 
...   ... 

कोई समझाने कृपया सकते हैं क्यों EAX रजिस्टर सहेजा जा रहा है और इन 4 भर में बहाल push निर्देश?

+2

मैंने देखा है कि कंपाइलर्स इस से डंबर चीजें करते हैं ... – Mysticial

+0

@ मिस्टिकियल: ओह लॉल ... यह पहली बार है जब मैंने ऐसा कुछ देखा है। :) जानकार अच्छा लगा। – Mehrdad

+7

शायद पहले पुश में एक शाखा है। –

उत्तर

9

इसके अलावा, शायद इसे रिलीज़ मोड में संकलित किया गया है, लेकिन उस चर को volatile के रूप में चिह्नित किया गया है, जो संकलक को बताता है कि इस तरह के चर के बिना यह परिवर्तन बदल सकता है, इसलिए इसे लगातार/लिखने के लिए मजबूर होना पड़ता है

+0

अह्ह्ह यह काफी संभव है! +1 धन्यवाद। – Mehrdad

+0

मुझे यकीन नहीं है कि 'अस्थिर' यहां एक अंतर डाल देगा। 'अस्थिर' स्मृति स्थान से संबंधित है, लेकिन ईएक्स एक रजिस्टर है; आप एक रजिस्टर को अस्थिर होने के रूप में चिह्नित नहीं कर सकते हैं। तो 'अस्थिर' प्रत्येक ऑपरेशन से ठीक पहले * eax पर * ebp-4] को फिर से लोड किया जा रहा है, लेकिन सहेजा नहीं जा रहा है। – Crashworks

+0

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

6

क्या यह डीबग मोड में बनाया गया था? यदि ऐसा है, तो कंपाइलर प्रत्येक स्थानीय चर को ढेर पर संग्रहीत करता है ताकि डीबगर उन्हें लगातार तरीके से ढूंढ सके।

ऐसे अनावश्यक स्टोर्स और रीलोड्स का अभिवाद ऑप्टिमाइज़ेशन में से एक है जो "रिलीज" मोड का गठन करता है।

+0

मेरा मानना ​​है कि यह * माना जाता है * रिलीज-मोड कोड होना चाहिए (संबंधित किसी भी चीज़ का कोई 'डीबग' संस्करण नहीं है जिसे मैं कहीं भी देख सकता हूं ...), लेकिन मुझे यकीन नहीं है ... मेरे पास स्रोत कोड नहीं है या तो। लेकिन +1 यह एक उचित अनुमान है, धन्यवाद। – Mehrdad

2

volatile या नहीं, केवल तकनीकी कारण है कि EAXविंडोज पर एक समारोह कॉल करने से पहले सीधे प्रारंभ करना होगा थे कि function__syscall घोषित किया जाता है, यानी विंडोज CS_SYSCALL बुला परंपरा का उपयोग करके। संकल्पनात्मक रूप से, यह संयुक्त राष्ट्र * एक्स x86_64 सम्मेलन के समान ही है जहां %al में %xmm रजिस्टरों में उत्तीर्ण फ्लोटिंग पॉइंट प्रकार तर्कों की संख्या शामिल है।

syscall विंडोज पर सम्मेलन बुला __cdecl के समान है, उलटे क्रम में स्टैक पर अर्थात समारोह आर्ग है, लेकिन इसके अलावा कि AL तर्क की संख्या की गणना शामिल हो के साथ; ऐसा इसलिए किया जाता है कि कर्नेल कोड जो आमतौर पर इसके अंतिम छोर पर होता है जानता है कि तर्क से पुनर्प्राप्त करने के लिए उपयोगकर्ता स्टैक पर कर्नेल स्टैक पर कितना डेटा पढ़ना है।

EAX 32 बिट विंडोज़ पर सभी कॉलिंग सम्मेलनों के लिए एक स्क्रैच रजिस्टर है, इसका मूल्य कभी भी कॉल कॉल पर संरक्षित नहीं होता है, कॉल करने से पहले इसे सीधे शुरू करना अनावश्यक होता है। भले ही यह वैरिएबल volatile था - क्योंकि एक साधारण पुनः लोड एक स्मृति बाधा नहीं है और पिछले स्टोर को "प्रतिबद्ध" नहीं करता है। इसके अलावा, [EBP - 4]स्टैक के भीतर है, इसलिए चर स्थानीय (और volatile क्वालीफायर कम समझ में आता है)।

यदि यह एक चूक अनुकूलन नहीं है तो यह

__syscall printf_syscall_conv(char *fmt, ...); 

void possibly_print_three_vals(char *fmt, int val1, int val2, int val3) 
{ 
    if (*strchr('%', fmt) == '\0') // if no "%" in fmt, pass no args 
     printf_syscall_conv(fmt); 
    else 
     printf_syscall_conv(fmt, val1, val2, val3); 
} 

यह क़यास आपके जैसे विधानसभा उत्पादन बना सकता है तर्क, जैसे की विभिन्न संख्या, परिकल्पित रूप के साथ एक __syscall function(...) की एक मंगलाचरण हो सकता है,।

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