2012-06-03 32 views
9

यह एक मामूली सवाल नहीं है।
नोट: मुझे शुद्ध एएसएम का उपयोग करने के लिए राय या सलाह की आवश्यकता नहीं है। मुझे वास्तव में ऐसा करने की ज़रूरत है जो मैं इस बारे में बात कर रहा हूं: इस साइन/शून्य के बिना इनलाइन एएसएम प्राप्त करने के लिए एक छोटा int परिणाम देने पर ऑप्टकोड का विस्तार करें।

मैं ऐसी लाइब्रेरी से निपट रहा हूं जो कई कार्यों के लिए 16-बिट शॉर्ट्स का दुरुपयोग करता है और मैं इसे अनुकूलित कर रहा हूं। मुझे इनलाइन एएसएम के साथ कुछ अनुकूलित फ़ंक्शन जोड़ने की आवश्यकता है। समस्या यह है कि कई जगहों पर फ़ंक्शन का परिणाम एक छोटा int को सौंपा गया है। यही है, कंपाइलर uxth या sxth arm opcode उत्पन्न करता है।

मेरा लक्ष्य उस समस्या से बचने और यह सुनिश्चित करने के लिए है कि यह बेकार ओपोड उत्पन्न नहीं हुआ है। सबसे पहले, मुझे छोटा int वापस करने के लिए अपने अनुकूलित फ़ंक्शन को परिभाषित करने की आवश्यकता है। इस तरह यदि इसे किसी इंट या कम int को सौंपा गया है तो परिणाम बदलने के लिए कोई अतिरिक्त ऑपोड नहीं है।

समस्या यह है कि मुझे कोई संकेत नहीं है कि उस int-> लघु रूपांतरण को कैसे छोड़ें जो संकलक मेरे स्वयं के फ़ंक्शन के अंदर उत्पन्न करता है।
गूंगा कास्ट जैसे: *(short*)(void*)&value काम नहीं करता है। कंपाइलर या तो स्टैक बनाने की समस्या के साथ गड़बड़ करना शुरू कर देता है, या यह परिणाम को साइन-विस्तार करने के लिए अभी भी उसी Sxth का उपयोग करता है।

मैं एकाधिक कंपाइलर्स के लिए संकलित करता हूं, और मैं इसे बांह के armcc कंपाइलर के लिए हल करने में सक्षम था, लेकिन मैं इसे जीसीसी (मैं 4.4.3 या 4.6.3 के साथ संकलित) के साथ नहीं कर सकता। Armcc के साथ मैं इनलाइन एएसएम कथन के अंदर छोटे प्रकार का उपयोग करें। जीसीसी में भी अगर मैं किसी कारण से शॉर्ट कंपाइलर का उपयोग करता हूं तो भी मानना ​​है कि साइन एक्सटेंशन की आवश्यकता है।

सी/सी ++ int को छोटा और इनलाइन एएसएम (एआरएम विशिष्ट) में परिवर्तित करें

यहां एक साधारण कोड स्निपेट है कि मैं जीसीसी के साथ काम नहीं कर सकता, यह काम करने के तरीके के बारे में कोई सलाह है?

नमूना फ़ाइल test.c फ़ाइल:

static __inline short CLZ(int n) 
{ 
    short ret; 
#ifdef __GNUC__ 
    __asm__("clz %0, %1" : "=r"(ret) : "r"(n)); 
#else 
    __asm { clz ret, n; } 
#endif 
    return ret; 
} 

//test function 
short test_clz(int n) 
{ 
    return CLZ(n); 
} 



यहाँ की उम्मीद है नतीजा यह है कि मैं armcc -c -O3 साथ मिलती है:

इस सरल उदाहरण के लिए मैं CLZ अनुदेश का उपयोग करेंगे
test_clz: 
    CLZ  r0,r0 
    BX  lr 

यहाँ अस्वीकार्य नतीजा यह है कि जीसीसी -c -O3 मुझे देता है:

test_clz: 
    clz r0, r0 
    sxth r0, r0 
    bx lr 

ध्यान दें कि अगर short ret; के बजाय आंतरिक चर int ret; के साथ सीएलजेड को फिर से लिखना है तो armcc जीसीसी के समान परिणाम उत्पन्न करता है।

त्वरित लाइन जीसीसी या armcc साथ एएसएम उत्पादन प्राप्त करने के लिए:
gcc -O3 -c test.c -o test.o && objdump -d test.o > test.s
armcc -O3 --arm --asm -c test.c

+1

आप इनलाइन असेंबली को क्यों नहीं छोड़ते हैं और असेंबली में लिखे गए पूरे फ़ंक्शन के रूप में बस अपना अनुकूलित बिट लिखते हैं? आपकी समस्या आपके सी फ़ंक्शन और इनलाइन एएसएम के मिश्रण से आती है। लेकिन एक सी फ़ंक्शन क्यों लिखें जिसमें केवल एएसएम का गुच्छा शामिल है? – TJD

+0

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

उत्तर

6

संकलनकर्ता परिवर्तन। विशेष रूप से जीसीसी में, आज आप कौन सी चालें समझते हैं, कल या कल काम नहीं करेंगे। और कंपाइलर्स (armcc, clang, आदि) में लगातार काम नहीं करेंगे।

1) शॉर्ट्स को हटाएं और इनट्स के साथ प्रतिस्थापित करें और इसे अभी खत्म करें, यह एक विकल्प है, यह कम से कम दर्दनाक समाधान है।

2) यदि आप विशिष्ट एएसएम चाहते हैं, तो विशिष्ट एएसएम लिखें, गड़बड़ न करें। एक विकल्प भी।

हालांकि कोड को लिखना बहुत संभव है जो लगातार दूसरे कोड की तुलना में बेहतर संकलित करता है, आप हमेशा उस कोड अनुक्रमों को प्राप्त नहीं कर सकते जो आप चाहते हैं, लगातार नहीं। आप अपने आप को लंबे समय तक चोट पहुंचा रहे हैं, यहां तक ​​कि अपना स्वयं का एएसएम समाधान भी लिखें। जिस समाधान का आप वास्तव में खोज रहे हैं वह है कोड के माध्यम से जाना और शॉर्ट्स को इनट्स के साथ प्रतिस्थापित करना, जो कोड उत्पन्न करने जा रहा है जो लगातार शॉर्ट्स रखने से बेहतर संकलन करेगा। इसमें सभी समय कम समय लगेगा और कंप्यूटर्स बदलने के रूप में हर मुट्ठी महीनों को फिर से लिखना नहीं होगा।

इसे एक बार पूरी तरह से नियंत्रित करने के लिए और सभी के लिए एएसएम को संकलित करने और अपमानित करने के लिए संकलित करना होगा, जिससे कार्य को एएसएम में छोड़ दिया जाएगा। कार्य को पूरा करने के लिए तेज़ और आसान, आप चाहते हैं कि आप इस ओवरहेड को हटाने के लिए चाहते हैं, केवल कुछ ऐसा छोड़ देता है जो बहुत ही रखरखाव योग्य नहीं है। दरअसल, चूंकि आपके पास armcc में एएसएम को संकलित करना चाहते हैं, तो उसके बाद आप gnu assembler आदतों की मूर्खता के लिए इसे पकड़ लें, और इसे एक समाधान के रूप में उपयोग करें (संभवतया एएसएम लिखना संभव है जो कम से कम बांह उपकरण और gnu के नीचे इकट्ठा होता है, कम से कम हाथों के विज्ञापन दिनों में, टूल्स तक पहुंच खोने से पहले मुझे बहुत अधिक समय नहीं था)।

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

1) शॉर्ट्स और उनके साइड इफेक्ट

2 के साथ रहते हैं) उन्हें ints

दिनों या हफ्तों या कुछ करने के लिए महीनों ले रहा है करने के लिए बदल जाता है एक बड़ा नहीं:

तो यहाँ

अपने वास्तविकता है सौदा। अधिकांश समय में दिन, सप्ताह, महीने लेते हैं कुछ करने से बचते हैं। और फिर आपको इसे वैसे भी करना है, इसलिए अब आपके पास 2xdays, 2xweeks, 2xmonths हैं ... आपको इसका कोई परीक्षण करना है या नहीं, इसका समाधान करना चाहिए, आप कोड बदल रहे हैं, ताकि इसमें कोई भिन्न कारक न हो फेसला। इनलाइन एएसएम के साथ कंपाइलर पर हैकिंग, आपका उच्चतम जोखिम है, और यदि परीक्षण समीकरण में भिन्न होता है तो इसका परीक्षण सबसे अधिक होना चाहिए। कुछ मुट्ठी भर जीसीसी संस्करणों की आवश्यकता है, साथ ही हर 6 महीने में retest।

आम तौर पर एएसएम समाधान तब होता है जब एबीआई बदलता है, शायद रीस्टस्टिंग के बीच 10 साल हो सकता है, और बस ठीक हो जाता है जब सी 64 बिट से 128 बिट तक हो सकता है। लेकिन 32 से 64 बिट संक्रमण अभी भी चल रहा है और हमने एआरएम 32 से 64 बिट संक्रमण/मिश्रण शुरू नहीं किया है (सभी 64 बिट के लिए 32 बिट आर्म प्रोसेसर को छोड़ नहीं पाएंगे, दोनों ही बने रहेंगे)। बैकएंड थोड़ी देर के लिए गड़बड़ होने जा रहे हैं, मैं अभी उनके साथ खेल नहीं खेलूंगा। स्वच्छ, पोर्टेबल, सी बनाना, जहां आप कोड में int के आकार पर भरोसा नहीं करते हैं (मान लें/32 न्यूनतम की आवश्यकता है लेकिन सुनिश्चित करें कि यह 64 बिट साफ है) आपका सबसे सस्ता समाधान है।

+0

हाय dwelch, बहुत लंबे और वर्णनात्मक उत्तर के लिए धन्यवाद। मैं आपके सभी बिंदुओं को स्पष्ट रूप से समझता हूं और मैंने वह सब किया है जहां मुझे वास्तव में इसकी आवश्यकता है। इस बिंदु पर मैं चाहता हूं कि जीसीसी को एसएक्सटीएच उत्पन्न न करें जहां मुझे पता है कि इसकी आवश्यकता नहीं है (मूल रूप से, मुझे विकल्पों के बारे में जानने की ज़रूरत नहीं है, शायद मैं उन सभी को जानता हूं)। मैं चाहता हूं कि केवल मेरे कंपाइलर के साथ उचित व्यवहार प्राप्त करें और मैं कर रहा हूं (भले ही भविष्य में कंपाइलर उस SXTH को फिर से जोड़ देगा, ठीक है)। – Pavel

+0

संक्षेप में, मैं उम्मीद करता हूं कि कुछ प्रकार के जीसीसी विशिष्ट "हैक" कास्ट प्रकार या कुछ अन्य इनलाइन एएसएम संशोधक शायद उस व्यवहार को प्राप्त करें। मैंने अलग-अलग जानवरों और संशोधकों की कोशिश की और कुछ भी मदद नहीं की। – Pavel

1

यह गति आप के बाद कर रहे हैं है, और नहीं कोड आकार, तो आप इस कोशिश कर सकते हैं:

static __inline short CLZ(int n) 
{ 
    short ret; 
#ifdef __GNUC__ 
    __asm__("clz %0, %1\n" 
      "bx lr" 
      : "=r"(ret) : "r"(n)); 
#else 
    __asm { clz ret, n; } 
#endif 
    return ret; 
} 

जोड़ने के लिए अपडेट किया गया: ऐसा नहीं है कि जीसीसी संकलक यहां सही काम कर रहा है मुझे लगता है। C में (C++ के विपरीत), ऐसी कोई ऐसी चीज़ नहीं है जो short लौटाती है - यह हमेशा स्वचालित रूप से int में परिवर्तित हो जाती है। तो आपके पास कंपाइलर को मूर्ख बनाने के अलावा कोई विकल्प नहीं है।क्या होता है यदि आप फ़ाइल नाम को test.cpp पर बदल दें?

+0

टोनी, मैं कोशिश करूंगा, यह सुनिश्चित नहीं करेगा कि क्या इनलाइन बीएक्स एलआर नकारात्मक रूप से अनुकूलक को प्रभावित कर सकता है, या यदि यह संभव है। जाहिर है, अगर यह केवल * रोलिंग उदाहरण प्राप्त कर रहा है तो यह समाधान नहीं है: सीएलजेड का संक्षिप्त संस्करण पूरे स्थान पर उपयोग किया जाता है और जहां इसका उपयोग किया जाता है SXTH उत्पन्न नहीं किया जाना चाहिए। कम लौटने की तरह ऐसी चीज है, भले ही यह 32-बिट रजिस्टर का उपयोग करे। लेकिन जीसीसी सोचता है कि इसे साइन-विस्तार करने की आवश्यकता है और मुझे पता है कि यह आवश्यक नहीं है। असल में यह है कि एसएक्सटीएच फ़ंक्शन सुनिश्चित करता है कि शीर्ष 16 बिट्स शून्य या हैं, लेकिन मुझे पता है कि उन कार्यों में इनपुट पहले से ही उचित लेआउट में है। – Pavel

+0

भी, मैं वास्तव में फ़ंक्शन ओवरलोडिंग इत्यादि जैसी कुछ सरल विशेषताओं को प्राप्त करने के लिए सी ++ संकलन का उपयोग करता हूं लेकिन इस उदाहरण में कोई अंतर नहीं है कि यह सी या सी ++ संकलन – Pavel

+0

मैंने अतिरिक्त बीएक्स एलआर की कोशिश की, ऐसा लगता है कि जीसीसी ओपोड नहीं करता है स्तर अनुकूलन: बीएक्स एलआर के बाद यह वही जोड़ी फिर से जोड़ता है: एसएक्सटीएच + एक और बीएक्स एलआर। संक्षेप में, अगर test_clz में यह शरीर था: CLZ (CLZ (ए)) तो परिणाम खराब होगा: जब रेखांकित किया गया, तो जीसीसी अभी भी बीएक्स एलआर विज्ञापन करता है जो अनजाने में कॉलिंग फ़ंक्शन को दबाएगा। शायद यह llvm/clang के साथ काम कर सकता है जहां यह कुछ ओपोड स्तर अनुकूलन करता है और यह पता लगा सकता है कि या तो एसएक्सटी आवश्यक नहीं है या वापसी इनलाइन एएसएम से ही की जाती है। – Pavel