2011-03-27 16 views
7

में लिखा एक समारोह की प्रस्तावना मैं डेल्फी 2010 का उपयोग कर रहा यह डेल्फी को बताने के लिए एक समारोह के लिए एक प्रस्तावना उत्पन्न नहीं करना संभव है निकाला जा रहा है? मैं इस तरह कुछ शुद्ध विधानसभा कार्यों लिख रहा हूँ:शुद्ध विधानसभा

procedure SomeAssembly; stdcall; 
begin 
    asm 
     ... 
    end; 
end; 

और मैं डेल्फी बताने के लिए इस समारोह के लिए एक प्रस्तावना और उपसंहार, जैसे सी ++ के __declspec(naked) सुविधा उत्पन्न करने के लिए नहीं करना चाहते हैं।

और इसलिए कोई भी अपने समय बरबाद करती है, मैं मदद प्रस्तावना के साथ काम करने के लिए इन कार्यों के लिए हो रही जरूरत नहीं है, मैं पहले से ही ऐसा कर सकता हूं। यह सिर्फ एक बड़ी असुविधा है और रखरखाव को एक बड़ी परेशानी बना देगा। मुझे अपनी लंबाई देखने के लिए कंपाइलर द्वारा जेनरेट किए गए प्रस्तावों का मैन्युअल रूप से निरीक्षण करना होगा, और यदि यह बदलता है, तो मेरा प्रोग्राम क्रैश हो जाएगा।

मैं भी मैं एक बाइट सरणी में बाइट्स की एक श्रृंखला के रूप में समारोह में लिख सकते हैं पता है, लेकिन है कि डेल्फी के प्रस्तावना की लंबाई को खोजने के जाने के लिए से भी बदतर हो जाएगा।

उत्तर

19

डेल्फी होने कोई तर्क कार्यों के लिए प्रस्तावनाएं या उपसंहार भी उत्पन्न नहीं करता है और रजिस्टर बुला सम्मेलन के साथ की घोषणा की। यदि आप प्रस्तावों के बिना काम करना चाहते हैं, तो उन्हें शून्य-तर्क, रजिस्टर-कॉलिंग-सम्मेलन कार्यों के रूप में घोषित करें। end ब्लॉक और सीधे विधानसभा में जाने - इसके अलावा, begin को छोड़ दें।

procedure SomeAssembly; // register; (implied) 
asm 
    // ... 
end; 

चूंकि आप प्रभावी रूप से कार्यों की प्रकृति के बारे में झूठ बोल रहे हैं, इसलिए उन्हें कॉल करना मुश्किल हो सकता है। यदि आपने एक फ़ंक्शन लागू किया है जैसे कि इसे पैरामीटर प्राप्त हुए हैं और एक अलग कॉलिंग सम्मेलन का उपयोग किया है, तो आपको यह सुनिश्चित करना होगा कि संकलक कॉल साइट पर इसके बारे में जानता है। ऐसा करने के लिए, एक फ़ंक्शन पॉइंटर घोषित करें जो घोषित प्रकार के बजाय आपके फ़ंक्शन के "वास्तविक" प्रकार को दर्शाता है। उदाहरण के लिए, अपने कार्य वास्तव में एक दो तर्क stdcall समारोह है, कुछ इस तरह की घोषणा:

type 
    TSomeAssemblyFunc = function (Arg1: Integer; Arg2: PAnsiChar): Boolean; stdcall; 
var 
    SomeAssemblyProc: TSomeAssemblyProc; 

अब, तो यह आपके समारोह में बताते हैं कि चर निर्दिष्ट:

SomeAssemblyProc := TSomeAssemblyProc(@SomeAssembly); 
if SomeAssembly(2, 'foo') then ... 

इसके अलावा लंघन करने के लिए प्रस्तावना और उपहास, संकलक इस फ़ंक्शन के लिए गलत RET निर्देश उत्पन्न करेगा (विभिन्न कॉलिंग सम्मेलन की वजह से), इसलिए आपको यह सुनिश्चित करना होगा कि आप संकलक के डिफ़ॉल्ट ret निर्देश देने के बजाय अपने कोड में ret 8 कहें।


डेल्फी के प्रस्तावना की लंबाई ढूँढना, तुच्छ है अगर आप एक काम डिबगर है:

  1. समारोह के शुरू में एक ब्रेकपाइंट सेट करें।
  2. कॉल समारोह।
  3. डिबगर ब्रेकप्वाइंट पर बंद हो जाता है, सीपीयू दृश्य में स्विच। निर्देश है कि प्रस्तावना को बनाने में
  4. देखो।
  5. उन निर्देशों के बगल में प्रदर्शित बाइट्स की गणना करें।
+0

एसओ इस पर उत्तर क्यों नहीं दे सकता? बहुत मददगार, धन्यवाद रॉब। –

+0

@ के। चार्ल्स: विशेषज्ञता के विभिन्न स्तर? यह एक जंगली अनुमान था, हालांकि, किसी के लिए कोई अपराध नहीं था। –

+0

जब आपके पास फ़ंक्शन पॉइंटर होता है तो क्या कोई अतिरिक्त स्तर नहीं है? व्यक्तिगत रूप से मैंने सोचा होगा कि टस्म अधिक उपयुक्त होगा। –

0

procedure SomeAssembly; stdcall; 
asm 
    ... 
end; 

चाल नहीं करता है?

+0

यदि मुझे सही तरीके से याद आ रहा है, तो 'stdcall' संकलक को फ्रेम पॉइंटर को सहेजने और पुनर्स्थापित करने के लिए प्रस्तावना और epilogue शामिल करने का कारण बनता है, भले ही कोई पैरामीटर न हो। –

1

this embarcadero docwiki के अनुसार आप को छोड़ सकते हैं begin और end आसपास और संकलक इसके बारे में कुछ सामान है को छोड़ देगा। लेकिन यदि आप वास्तव में शुद्ध असेंबलर चाहते हैं, तो अपने फ़ंक्शन को एक अलग असेंबलर फ़ाइल में क्यों न रखें, इसे टस्म के साथ इकट्ठा करें (exe tasm32 नाम दिया गया है) और उससे लिंक करें। फिर आप डेल्फी कोड में assembler निर्देश का उपयोग करेंगे।

+0

@downvoters, कृपया समझाएं। टीएएसएम डेल्फी का हिस्सा है और यह 100% शुद्ध असेंबलर के साथ काम करने का प्राकृतिक तरीका है। क्या यह रणनीतिक मतदान था? –