2014-05-08 12 views
5

मुझे एक ऐसा कार्य सौंपा गया है जो सैद्धांतिक रूप से बहुत कठिन नहीं है। असेंबलर कोड (एएसएम) का उपयोग करके एक सी चर बदलना चाहिए। मैंने यह किया है और यह काम करता है, लेकिन असाइनमेंट का दूसरा भाग प्लेसहोल्डर्स (%) का उपयोग किए बिना एक ही काम करना है।प्लेसहोल्डर्स का उपयोग किये बिना सी में असेंबलर का उपयोग

मैं यहां एक नुकसान में हूं और कुछ शोध के बाद मुझे अभी भी समाधान नहीं मिला है। परिवर्तक प्राप्त करने के लिए प्लेसहोल्डर्स का उपयोग किये बिना मैं असेंबलर कोड में सी चर का उपयोग कैसे कर सकता हूं?

volatile uint8_t number = 1; 
    volatile uint8_t *number_pointer = &number; 

    asm volatile(
     "ld r20, %a0" "\n\t" 
     "lsl r20" "\n\t" 
     "st %a0, r20" "\n\t" 
     "breq resetten" "\n\t" 
     "ret" "\n\t" 

     "resetten:" "\n\t" 
     "ldi r20, 1" "\n\t" 
     "st %a0, r20" 
      : "+e" (number_pointer) 
    ); 

संक्षेप में:: मैं कैसे उपयोग कर सकते हैं और परिवर्तन "number_pointer" एक% का उपयोग किए बिना

यहाँ प्लेसहोल्डर के साथ कोड है? (कोड 128 गुना होने तक "संख्या" है, फिर यह 1 से शुरू होता है।)

+0

यदि परिवर्तनीय को बदलने के लिए स्थानीय (स्टैक पर) है तो आप कंपाइलर-निर्भर धारणाएं बना सकते हैं कि वेरिएबल स्टैण्ड पॉइंटर से संबंधित स्मृति में कहां स्थित है। –

+0

आपको रजिस्टरों में चर प्रस्तुत करने के लिए दूसरा ':' जोड़ना होगा (जैसे 'asm ("blabla":: "a" (number_pointer));'), लेकिन eax में number_pointer होगा ... हालांकि, उपयोग करना एटी एंड टी वाक्यविन्यास आप अभी भी इसका उपयोग करने के लिए '%% eax' का उपयोग करेंगे। यदि आवश्यकता '%' का उपयोग नहीं कर रही है (जैसा कि आप अंत में इंगित करते हैं), तो यह काम नहीं करता है ... यदि आवश्यकता __placehold__ का उपयोग नहीं कर रही है, तो ऐसा होगा (आप एक रजिस्टर का उपयोग करेंगे)। – Jcl

+1

stat_pointer को स्थैतिक या वैश्विक के रूप में घोषित करने के बारे में कैसे? फिर आप प्रतीक नाम के माध्यम से सीधे एएसएम से इसका उपयोग कर सकते हैं। मैं इसे उत्पादन कोड के लिए अनुशंसा नहीं करता, लेकिन पहेली हल करने के लिए इसे काम करना चाहिए। –

उत्तर

1

डेविड सुझाव पर टिप्पणी करने के लिए (अगर मैं पर्याप्त प्रतिष्ठा प्राप्त करता हूं तो मैं इसे टिप्पणी के रूप में पोस्ट करूंगा): "स्मृति" संकेत का उपयोग करें clobbered क्षेत्र में, asm ("nop" ::: "स्मृति") की तरह;

यह जीसीसी कि एएसएम बयान स्मृति को संशोधित करता है और बताता है कि चर फिर से लोड करने के लिए, आदि

उदाहरण के लिए,

static int foo; 
int bar() 
{ 
    foo = 1; 
    __asm__("":::"memory"); 
    return foo; 
} 

साथ की जरूरत है हम कोडांतरक कोड के

डंप मिल फ़ंक्शन बार के लिए:

0x0000000000000000 <+0>:   movl $0x1,0x0(%rip)  # 0xa <bar+10> 
    0x000000000000000a <+10>:  mov 0x0(%rip),%eax  # 0x10 <bar+16> 
    0x0000000000000010 <+16>:  retq 

जबकि "स्मृति" के बिना, वें परिवर्तनीय मान का ई पुनः लोड गुम है।

+0

हालांकि यह काम कर सकता है, यह अतिरिक्त प्रदर्शन मुद्दों को पेश कर सकता है। चूंकि "मेमोरी" का अर्थ है कि एएसएम सभी मेमोरी को पढ़/लिख सकता है, इसलिए कंपाइलर को केवल एक रजिस्टर से अधिक फ्लश (और पुनः लोड) करना पड़ सकता है। फिर, बेहतर समाधान केवल चर या इनपुट के रूप में चर को सूचीबद्ध करना है। –

+0

हां, यह समझा जाता है, इनपुट और आउटपुट का सही ढंग से उपयोग करना हमेशा पसंदीदा समाधान होता है। ओपी के सवाल के संदर्भ में, यह स्पष्ट रूप से एक विकल्प नहीं है, इसलिए यदि आप किसी वैश्विक चर या किसी अन्य स्मृति को लिखना चाहते हैं, तो आपके पास "मेमोरी" को सूचीबद्ध करने के लिए * है, इसके बिना प्रोग्राम थोड़ा सा हो सकता है तेज़, लेकिन यह गलत भी हो सकता है, इस पर निर्भर करता है कि संकलक ऑप्टिमाइज़ मानों को अनुकूलित करता है। – akruppa

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