इस विषय से संबंधित कुछ प्रश्नों (और उत्तरों) पर एक नज़र डालने के बाद, मैंने godbolt

#include <iostream>


class TwoInts
{
public:
    TwoInts( ) = default;

    const int& getAByRef( ) const;

    int getAByVal( ) const;

private:
    int a;
    int b;
};

const int& TwoInts::getAByRef( ) const
{
    return a;
}

int TwoInts::getAByVal( ) const
{
    return a;
}


int main( )
{
    TwoInts ti;

    const int& num1 { ti.getAByRef( ) };
    const int num2 { ti.getAByVal( ) };

    //std::cout << num1 << ' ' << num2 << '\n';
}

अब मुझे दो सदस्य कार्यों getAByRef और getAByVal के लिए अलग-अलग कोड उत्पन्न होते हैं:

TwoInts::getAByRef() const:
        mov     rax, rdi
        ret
TwoInts::getAByVal() const:
        mov     eax, DWORD PTR [rdi]
        ret

मैं इसकी सराहना करूंगा यदि कोई समझा सके कि वे दो अलग-अलग असेंबली निर्देश क्या कर रहे हैं?

1
digito_evo 25 पद 2021, 13:20
मुझे समझ में नहीं आता कि प्रश्न का सी ++ से क्या लेना-देना है (ऐसा लगता है कि "इन असेंबली ऑपकोड्स का क्या मतलब है?", और उनका मतलब वही होगा चाहे आपको संकलन करके असेंबली स्रोत मिल गया हो C++ प्रोग्राम या इसे हाथ से लिखना)। मुझे यह भी समझ नहीं आ रहा है कि आप किस प्रकार का उत्तर मांग रहे हैं - हम चीजों को शून्य में "व्याख्या" नहीं कर सकते, क्योंकि हमारे पास यह जानने का कोई तरीका नहीं है कि आप पहले से ही क्यों नहीं समझते हैं। कृपया meta.stackoverflow.com/questions/284236 पढ़ें, और ASM ट्यूटोरियल देखने पर विचार करें।
 – 
Karl Knechtel
25 पद 2021, 13:23
धन्यवाद! अच्छी तरह से समझाया। अब मेरे पास एक विचार है कि क्या हो रहा है। मुझे लगता है कि आप इसे उत्तर के रूप में भी पोस्ट कर सकते हैं।
 – 
digito_evo
25 पद 2021, 13:32

1 उत्तर

सबसे बढ़िया उत्तर

प्रत्येक सदस्य फ़ंक्शन को एक अंतर्निहित प्रथम तर्क के रूप में this मिलता है। उस विशेष कंपाइलर द्वारा उपयोग किए जाने वाले ABI में (Itanium ABI), पहला तर्क rdi रजिस्टर में पास किया जाता है और rax (eax) रजिस्टर में एक मान लौटाया जाता है (यदि यह मामूली है, और यहां है)।

पहले मामले में, जब आप संदर्भ द्वारा a लौटाते हैं, तो आप वास्तव में a का पता वापस कर रहे होते हैं। a पहला सदस्य है, इसलिए उसका पता वही है जो वस्तु का है, यानी this। इसलिए, आप बस rax को rdi पर सेट करें।

दूसरे मामले में, जब आप मूल्य के आधार पर a वापस करते हैं, तो आपको वास्तविक डीरेफ्रेंसिंग करने की आवश्यकता होती है। यही DWORD PTR [rdi] कर रहा है। DWORD PTR का मतलब है कि आप 4 बाइट्स (sizeof(int)) लाना चाहते हैं।

यदि आप कुछ डेटा सदस्य को a से पहले रखते हैं, तो आपको rdi में एक अतिरिक्त ऑफ़सेट जोड़ा हुआ दिखाई देगा।

1
Evg 25 पद 2021, 13:53
वाह, यह इसे और स्पष्ट करता है। अब मेरा दूसरा प्रश्न यह है कि वहाँ DWORD PTR का उद्देश्य क्या है? मेरा मतलब है कि क्या यह rdi को संदर्भित करता है? क्या rdi एक क्वाडवर्ड रजिस्टर नहीं है?
 – 
digito_evo
25 पद 2021, 13:39
1
rdi एक पता रखता है। DWORD बताता है कि हम उस पते से कितने बाइट प्राप्त करना चाहते हैं। int को char में बदलें, और यह BYTE PTR होगा।
 – 
Evg
25 पद 2021, 13:41
ओह! इसलिए उदाहरण के लिए यदि हम rdi से int64_t प्राप्त करना चाहते हैं तो हम QWORD PTR या ऐसा ही कुछ उपयोग करेंगे? क्षमा करें यदि मैं अजीब प्रश्न पूछ रहा हूँ।
 – 
digito_evo
25 पद 2021, 13:43
1
बिल्कुल।
 – 
Evg
25 पद 2021, 13:45