2010-02-22 17 views
8

से कॉल करता हूं तो मैं सी ++ फ़ंक्शंस में तर्क कैसे पास करूं, इसलिए, मैं एक C++ dll से फ़ंक्शंस कॉल करने में सक्षम होना चाहता हूं। कुछ कारणों से, मैं उन्हें अपने सी ++ कोड में __asm ​​ब्लॉक से कॉल करना चाहता हूं। मेरा प्रश्न यह है: मैं जानता हूँ कि इससे पहले कि मैं फ़ंक्शन को कॉल करें, मैं समारोह के बुला convention.However द्वारा निर्दिष्ट क्रम में स्टैक पर अपने तर्कों पुश करने के लिए है, मैं बस कुछ इस तरह कर सकते हैं:जब मैं उन्हें इनलाइन असेंबली

int a=5; 
double b = 5.0; 
__asm{ 
     push b 
     push a 
     call functionAddress 
} 

मुझे चिंता है कि मुझे यह याद आ रहा है कि मुझे याद है कि असेंबली में मानक शब्द का आकार 2bytes है, जबकि सी ++ में int का आकार आमतौर पर 4bytes और 8 बाइट्स डबल के लिए होता है। इसलिए, ऊपर दिए गए उदाहरण में, क्या मैं वास्तव में प्रत्येक चर के पूर्ण मूल्य, या केवल बाइट्स के पहले जोड़े को धक्का दे रहा है? यदि उपरोक्त कोड सही नहीं है, तो ऐसा करने का सही तरीका क्या होगा? साथ ही, यदि हम जिस फ़ंक्शन को कॉल कर रहे हैं वह दोहरा देता है, तो यह मान कहां संग्रहीत किया जाता है? मुझे लगता है कि यह एक रजिस्टर में नहीं हो सकता है, क्योंकि यह केवल 32 बिट्स (4 बाइट्स) स्टोर कर सकता है। इस गड़बड़ी के साथ कोई भी मदद की सराहना की जाएगी :)

+2

जब आपने इसे आजमाया तो क्या हुआ? – Seth

+0

मुझे युगल के साथ समस्या हो रही है: मैंने खुद को डीएलएल में एक टेस्ट फ़ंक्शन बनाया है जो डबल तर्क लेता है और यदि इनपुट 5.0 से बड़ा है तो यह 1 लौटाता है। बात यह है कि मैंने समारोह को असेंबली से कुछ बार कॉल करने का प्रयास किया तर्क 7.45454 के साथ और वापसी मूल्य हमेशा एक जैसा नहीं है। –

उत्तर

13

जैसे डबल्स खिलाड़ियों के रूप में 8-बाइट मूल्यों धक्का करने के लिए, आप एक नियमित PUSH अनुदेश का उपयोग करने में सक्षम नहीं होगा। और न ही आप फ्लोटिंग-पॉइंट पैरामीटर (या युगल) को फ़्लोटिंग-पॉइंट स्टैक पर दबाते हैं। आपको इन वसा पैरामीटर को 'हाथ से' ढेर पर रखना होगा। उदाहरण के लिए, π को फ़ंक्शन के पैरामीटर के रूप में धक्का देने के लिए f:

__asm { 
    FLDPI     // load pi onto FP stack 
    SUB ESP,8    // make room for double on processor stack 
    FSTP QWORD PTR [ESP]  // store pi in proc stack slot (and pop from FP stack) 
    CALL f 
    ADD ESP,8    // clean up stack (assuming f is _cdecl) 
    } 
1

आम तौर पर, आप कंप्यूटर के पूर्ण आकार को दबाएंगे शब्द। यह चिप के अनुसार भिन्न होता है, लेकिन 32 बिट इंटेल पर 4 बिट्स होगा, और 64 बिट इंटेल पर 8 होगा (कंपाइलर के आधार पर - विजुअल स्टूडियो अभी भी केवल आईए 32 असेंबली का समर्थन करता है - इसलिए 4 बाइट्स)।

सबसे अच्छा जवाब आपके विशिष्ट कंपाइलर के लिए प्रलेखन को देखना है।

4

32-बिट x86 आर्किटेक्चर स्वचालित रूप से स्टैक पर 32 बिट्स पर धक्का दिया जाता है।

कुछ ऐसा है जो आपको ध्यान में रखना है। यदि आप जिस फ़ंक्शन को कॉल कर रहे हैं, वह __cdecl कॉलिंग कन्वेंशन का उपयोग करता है, तो आपको बाद में जो भी धक्का दिया गया है उसे "पॉप" करना होगा। हालांकि, __stdcall कार्यों के लिए आपको यह नहीं करना चाहिए।

extern "C" int __cdecl function1(int, double); 
extern "C" double __stdcall function2(char, char*); 

int a = 5; 
double b = 5.0; 
int retval1; 
char c = '5'; 
char *d = "Hello"; 
double retval2; 

__asm { 
    push b 
    push a 
    call function1 
    add esp, 4*2 // "pop" what we pushed 
    mov retval1, eax 
    push d 
    push c 
    call function2 
    mov retval2, eax 
} 
+2

दिमाग की अतिरिक्त शांति के लिए, यह पता लगाने के बाद कि यह * क्या होना चाहिए, सी ++ से समकक्ष कॉल करें, ऑप्टिमाइज़ेशन अक्षम के साथ संकलित करें, और असेंबली आउटपुट देखें। यह मोटे तौर पर मेल खाना चाहिए जो आप कर रहे हैं। –

+1

लेकिन फिर, आप एक डबल को कैसे दबाएंगे? सी ++ में यह 8 बाइट्स होना चाहिए, है ना? –

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