2012-04-02 11 views
8

मैं सी/ऑब्जेक्टिव-सी में उच्च स्तरीय कॉलिंग के साथ उपयोग के लिए कुछ ट्रैम्पोलिन फ़ंक्शंस के साथ काम कर रहा हूं, Apple does it के रास्ते पर मामूली मोड़।i386 में स्टैक से तर्कों को हटाने, एआरएम असेंबली

आप पर सभी तरह ऑब्जेक्टिव-सी IMP काम करता है के साथ परिचित हैं, तो यह मूल रूप से एक समारोह सूचक जहां पहले दो तर्क संदेश का रिसीवर और संदेश चयनकर्ता के नाम हैं, void(*)(id obj, SEL sel, ...) रूप में इस तरह है। रनटाइम के हाल के संस्करणों में सी ब्लॉक का उपयोग करके रन टाइम पर विधि कार्यान्वयन को संश्लेषित करने की अनुमति मिलती है, जैसे void(^)(id obj, ...)। इन ब्लॉकों में चयनकर्ता नहीं है; रनटाइम एक ट्रैम्पोलिन बनाता है जो रिसीवर के साथ चयनकर्ता को ओवरराइट करता है, ब्लॉक पॉइंटर के साथ रिसीवर, और उसके बाद इसे निष्पादित करने पर चलता है।

मैं, जो या तो पहले दो तर्कों की नहीं होने शामिल अस्पष्ट समान कुछ करने के लिए इतना है कि इस ब्लॉक के लिए तर्क पारंपरिक विधि भेजने के तर्कों के रूप में ठीक उसी हैं चाहते हैं, के साथ साथ निष्पादन के लिए ब्लॉक सूचक उद्देश्यों, यानी, void(*)(Block *, ...)। इसके लिए केवल ब्लॉक पॉइंटर में कॉपी करना आवश्यक है, और मुझे लगता है कि एक तर्क से छुटकारा पा रहा है।

__a1a2_tramphead_argonly: 
    popl %eax 
    andl $0xFFFFFFF8, %eax 
    subl $0x1000, %eax 
    movl 4(%esp), %ecx // self -> ecx 
    movl %ecx, 8(%esp) // ecx -> _cmd 
    movl (%eax), %ecx // blockPtr -> ecx 
    movl %ecx, 4(%esp) // ecx -> self 
    jmp *12(%ecx) // tail to block->invoke 

यहाँ विधानसभा मैं एआरएम पर है:

__a1a2_tramphead_argonly: 
    // calculate the trampoline's index (512 entries, 8 bytes each) 
#ifdef _ARM_ARCH_7 
    // PC bias is only 4, no need to correct with 8-byte trampolines 
    ubfx r1, r1, #3, #9 
#else 
    sub r1, r1, #8    // correct PC bias 
    lsl r1, r1, #20 
    lsr r1, r1, #23 
#endif 

    // load block pointer from trampoline's data 
    adr r12, __a1a2_tramphead_argonly // text page 
    sub r12, r12, #4096   // data page precedes text page 
    ldr r12, [r12, r1, LSL #3] // load block pointer from data + index*8 

    // shuffle parameters 
    mov r1, r0     // _cmd = self 
    mov r0, r12     // self = block pointer 

    // tail call block->invoke 
    ldr pc, [r12, #12] 

इसी कोड x86_64 के लिए मौजूद है, ऊपर दिया गया कोड अब तक सीधे ऐप्पल से है। व्यक्तिगत ज्ञान के लिए, मैं सोच रहा हूं कि तर्क को उत्तेजित करने के साथ कहां से शुरू करना है, ताकि पहला तर्क (जो रेसीवर होता था) ब्लॉक शब्दशः है, दूसरा पहला वास्तविक तर्क है, और इसी तरह।

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

+1

सावधान रहें, वर्तमान में कई लिनक्स डिस्ट्रोज़ एआरएम हार्ड-फ्लोट एबीआई में जाने की प्रक्रिया में हैं। यह फिर से आपके लिए सबकुछ तोड़ देगा। – ams

+0

यह दिलचस्प है, मैं इसे भविष्य के लिए ध्यान में रखूंगा। हालांकि, यह ज्यादातर डार्विन को लक्षित कर रहा है। धन्यवाद! संपादित करें: इसका मतलब है कि कम से कम समय के लिए एआरएमवी 6 और एआरएमवी 7। – zwaldowski

उत्तर

2

आईओएस एबीआई प्रभावी रूप से एएपीसीएस को शामिल करता है और केवल अंतर को परिभाषित करता है, इसलिए आप पहले http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0042d/index.html से शुरू करना चाहेंगे। फिर ऐप्पल की आईओएस एबीआई फंक्शन कॉल गाइड पढ़ें (जो मुझे लगता है कि आपको एक्सेस करने के लिए एक भुगतान आईओएस देव केंद्र सदस्यता की आवश्यकता है)।

नियमों को संक्षेप में एक ObjC छोटा सा भूत कॉल करने के लिए:

  • स्वयं R0 में चला जाता है
  • _cmd
  • पहले पूर्णांक या सूचक तर्क R2 में चला जाता है
  • दूसरे पूर्णांक या सूचक तर्क आर 1 में चला जाता है R3 में चला जाता है
  • आगे की सभी तर्कों ढेर पर जाने
mov r0, r2 
mov r1, r3 
:इसलिए, यदि आप केवल अप करने के लिए 2 पैरामीटर, उनमें चल बिन्दु/int64_t/struct में से कोई भी, स्वयं और _cmd तर्क को दूर करने के साथ बहस को देख रहे हैं R0-R4 फेरबदल का मामला है

mov r3, r1 
mov r2, r0 
ldr r1, [address of _cmd] 
ldr r0, [address of self] 

एप्पल के ब्लॉक ट्रैम्पोलिन के मामले में, वे क्या कर रहे हैं बदलाव ला रहा है:

या, एक समारोह है कि दो पैरामीटर लेता है और स्वयं crams और एक छोटा सा भूत को अग्रेषित करने से पहले में _cmd लिखने के लिए, यह सिर्फ इस है प्रभावी रूप से [ब्लॉक foo] में [foo performBlockOnSelf: block] को कॉल करें।जैसा कि आप कहते हैं, ब्लॉक पॉइंटर आर 0 (सामान्य स्व स्थिति) में समाप्त होता है और लक्ष्य पैरामीटर foo r1 (सामान्य _cmd स्थिति) में समाप्त होता है। यदि ब्लॉक वास्तव में आईएमपी थे, निश्चित रूप से, यह बकवास होगा, क्योंकि foo एक एसईएल नहीं है, लेकिन वे नहीं हैं, इसलिए यह कोई समस्या नहीं है।

आपके कथन से "मैं कुछ अस्पष्ट रूप से ऐसा करना चाहता हूं जिसमें पहले दो तर्कों में से कोई भी शामिल न हो, ताकि इस ब्लॉक के तर्क पारंपरिक विधि के तर्कों के समान सटीक हों," मैं हूं पूरी तरह स्पष्ट नहीं है जो दो बातें तुम क्या करने की कोशिश कर रहे:

  1. एक "प्रतिनिधि" वस्तु (सी # संदर्भ में) को परिभाषित करें, मूल रूप से अपने लक्ष्य के साथ एक ब्लॉक में निर्माण समय में पके हुए। इस मामले में, आप केवल ब्लॉक सूचक के बजाय प्रतिनिधियों की कुछ तालिका से आर 0 (ब्लॉक पॉइंटर) और आर 1 (लक्ष्य) दोनों देखना चाहते हैं। लेकिन आपके पास उस तालिका को स्थापित करने में कोई कंपाइलर सहायता नहीं होगी - जिसका अर्थ है कि आप इसे सेट अप कर सकते हैं और इसे शुद्ध सी में एक्सेस कर सकते हैं और यह एक सुविधाजनक असेंबली ट्रैम्पोलिन के रूप में सुविधाजनक और निर्माण करेगा। (आप ओबीजेसी शब्दकोशों के माध्यम से भी ऐसा कर सकते हैं, प्रदर्शन के कुछ नुकसान के साथ जो अभ्यास में कोई फर्क नहीं पड़ता है।)

  2. एक नियमित संदेश को एक ब्लॉक में बदलें, जिसमें सब कुछ संग्रहीत हो रहा है ताकि जब ऐप्पल का ट्रैम्पोलिन कोड कॉल करने का प्रयास करता है यह ब्लॉक पारंपरिक पैरामीटर के साथ समाप्त होता है जो ब्लॉक पैरामीटर के बजाय पैरामीटर भेजता है। यदि यह आपका लक्ष्य है, तो संदेशों को ब्लॉक में बदलने की कोशिश करने के बजाय संदेश के चारों ओर एक ब्लॉक रैपर का उपयोग करना आसान और अधिक सुरक्षित है, और मुझे संदेह है कि इससे कोई फर्क नहीं पड़ता कि दक्षता या लचीलापन लागत होगी।

+0

उत्तर देने में इतनी देर लगने के लिए मेरी माफ़ी, मैंने इसे उत्तर दिया है और इसे उचित उत्तर के रूप में चिह्नित किया है क्योंकि यह अप्रैल में वही था जो मैं चाहता था। कुछ लोगों के साथ परामर्श करने के बाद, जिन्होंने समान काम किया था, हम साथ गए - और तैनात - libffi का उपयोग कर एक समाधान। उस दूसरे तर्क को हटाने (_cmd) बिल्कुल अनिवार्य था। तर्कों के सामने लोडिंग (कम से कम एआरएम पर) के बीच, हमारे ढांचे के उपयोगकर्ताओं को चार तर्कों या गैर-विधियों के तरीकों तक सीमित किए बिना करना मुश्किल होगा। हमारा अंतिम समाधान अपने पूर्ववर्ती की तुलना में तेज़ और अधिक कार्यात्मक था, इसलिए मैं खुश हूं। धन्यवाद! – zwaldowski

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