2016-11-29 17 views
5

एक Arduino का उपयोग करके, मुझे अपने कंप्यूटर विज्ञान वर्ग के लिए एटम एवीआर असेंबली में एक फ़ंक्शन लिखना है जो एक हस्ताक्षरित 8-बिट बाइट को एक हस्ताक्षरित 16-बिट पूर्णांक में परिवर्तित करता है। मुझे किसी भी शाखा निर्देशों का उपयोग करने की अनुमति नहीं है (लेकिन छोड़ें ठीक हैं)।मैं एक हस्ताक्षरित 8-बिट बाइट को असेंबली में हस्ताक्षरित 16-बिट पूर्णांक में कैसे परिवर्तित करूं?

मैं जानता हूँ कि यह गलत है, लेकिन यह सब मैं अब तक मिल गया है है:

.global byteToInt 
byteToInt: 
    sbrc r24, 7 
    ldi r25, 1 
    asr r25 
    ret 

किसी को कैसे मैं इस समारोह का काम करते हैं पता है? कोई भी सहायताकाफी प्रशंसनीय होगी!

+1

पर हस्ताक्षर किए संख्या के लिए कौन सा प्रारूप शिक्षक परोक्ष संभालने रहा है? दो का अनुपूरण? –

+1

@MargaretBloom: AVR के साइन-ध्वज की तरह यह बिट्स की 2 के पूरक व्याख्या के आधार पर सेट है लगता है, इसलिए मुझे लगता है कि कह बिना चला जाता है लगता है। इसके अलावा [एनईजी निर्देश] (http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_NEG.html) 2 की पूरक अस्वीकृति करता है। –

+0

@ पीटरकॉर्डस एह, शायद या शायद नहीं। पाठ्यक्रम के दो पूरक मानना ​​उचित है लेकिन अन्य हस्ताक्षरित प्रतिनिधित्वों को लागू करने के बारे में एक अभ्यास हो सकता है (वास्तव में आईएसए से समर्थन की कमी के कारण)। मैंने हालांकि दो पूरक भी माना। –

उत्तर

3

अच्छी तरह से आपको ऊपरी छोर में प्रत्येक बिट पर char के साइन बिट की प्रतिलिपि बनाने की आवश्यकता है। अधिकांश आर्किटेक्चर पर, सीधा एक रजिस्टर और अंकगणितीय-दाएं-इसे 7 तक प्रतिलिपि बनाना होगा। लेकिन एवीआर में केवल shift-by-1 instruction है, इसलिए हम इसे कुशलता से नहीं कर सकते हैं।

सशर्त रूप से 0 या -1 को एक रजिस्टर में प्राप्त करने के लिए एक और चाल subtract-with-borrow0 - C प्राप्त करने के लिए स्वयं से एक रजिस्टर है। जैसे sbc r25, r25

अब 8-बिट संख्या ऋणात्मक होने पर हमें कैरी ध्वज सेट करने का एक तरीका चाहिए, यानी यदि यह> 127 है जब एक हस्ताक्षरित पूर्णांक के रूप में माना जाता है, क्योंकि सी हमेशा चीजों की हस्ताक्षरित व्याख्या के आधार पर सेट की जाती है। एवीआर की एक तुलना-तत्काल निर्देश है, CPI, लेकिन यह केवल आर 16-आर 31 के लिए काम करता है, न कि कम रजिस्टरों के लिए। साथ ही, यह सी फ्लैग को जो हम वास्तव में चाहते हैं उसके विपरीत सेट करता है, इसलिए हमें परिणाम को बदलने के लिए एक और निर्देश का उपयोग करना होगा। तो मुझे लगता है कि हम एक रजिस्टर में एक मूल्य के खिलाफ दूसरी तरह की तुलना कर से बेहतर कर रहे हैं:

; Most efficient way, I think: 
sign_extend: 
    ldi r25, 127  ; can be hoisted out of loops, and any reg is fine. 

    cp r25, r24  ; C = (r24 < 0) 
    sbc r25, r25  ; r25 = (r24 < 0) ? -1 : 0 
    ; result in r25:r24 

और भी बेहतर, यदि आप एक पाश में ऐसा करने की जरूरत है, तो आप 127 एक अलग रजिस्टर में रख सकते हैं। एक प्रतिबंध है जिस पर प्रयोग किया जाता है रजिस्टर से बचने के लिए

; slightly worse: only works with r16-r31, and worse in loops 
sign_extend: 
    cpi r24, 127  ; C = (r24 < 128U) = ((signed)r24 >= 0) 
    sbc r25, r25  ; r25 = (r24>=0) ? -1 : 0 
    com r25    ; ones-complement negation: 0 : -1 

या, दूसरी तरह के तुलना करते हैं:

भाकपा के साथ

, आप ऐसा करते हैं होता

मैं AVR के साथ काम किया कभी नहीं किया है , इसलिए मैं इसे निर्देश सेट संदर्भ मैनुअल से बस कर रहा हूं जिसे Google मिला (और अन्य आईएसए के लिए एएसएम का ज्ञान, जैसे कि x86 और एआरएम)। उन दस्तावेज़ों के मुताबिक, उन सभी निर्देश 1 शब्द (2 बाइट्स) हैं, 1 चक्र विलंबता के साथ।


अच्छा अनुदेश दृश्यों को खोजने के लिए हमेशा की तरह एक संकलक पूछने के लिएAVR gcc4.5 -O3 on godbolt करता है:

short sign_extend(signed char a) { return a; } 

sign_extend: 
    mov r18,r24  ;; IDK why gcc uses r18 and r19. 

    clr r19 
    sbrc r18,7 
    com r19 

    mov r25,r19 
    ret 

तो यह zeros R19, तो SBRC का उपयोग करता है यह वही है gcc4.5 करता है की तुलना में बेहतर है R18 के साइन बिट (बिट 7) के आधार पर सशर्त रूप से लॉजिकल-नहीं (COM) निष्पादित करने के लिए।

मुझे यकीन नहीं है कि अतिरिक्त एमओवी क्या हैं। मुझे यह भी यकीन नहीं है कि यह सभी बिट्स को इनपुट-निर्भरता के साथ सेट करने के बजाय शून्य को क्यों बदलता है। (उदाहरण के लिए ldi r19, $FF, या SBR alias for it। यदि आउट ऑफ़ ऑर्डर-निष्पादन एवीआर कभी अस्तित्व में है, तो यह अधिक कुशल होगा।: पी

मुझे यकीन नहीं है कि एमओवी निर्देश क्या हैं। एसबीआरसी गैर- विनाशकारी।AFAICT तो, एक वैध कार्यान्वयन

sign_extend: 
    clr r25 
    sbrc r24,7 
    ldi r25, $FF 
    ret 

होगा यह अभी भी CP/SBC से भी बदतर है, क्योंकि SBRC 2 चक्र लेता है, तो छोड़ लिया जाता है।


मुझे लगता है कि आर 25 के पुराने मूल्य पर एसबीसी की "झूठी निर्भरता" एवीआर पर एक बात नहीं है। आउट-ऑफ-ऑर्डर x86 सीपीयू पर, केवल एएमडी sbb eax, eax को ईएक्स के पुराने मूल्य से स्वतंत्र होने के रूप में पहचानता है, और केवल झंडे के आधार पर। इंटेल सीपीयू बस इसे सामान्य रूप से चलाते हैं। तो गैर एएमडी CPUs पर (वे xor eax,eax स्वतंत्र रूप में, और it's the standard zeroing-idiom for x86 की तरह निर्देश पहचान कर सकते हैं।)

, अगर पिछले कोड कि EAX लिखा एक लोड है कि कैश में याद किया, या कुछ और उच्च विलंबता के साथ वैसा ही किया, sbb eax, eax ध्वज तैयार होने के बावजूद निष्पादित नहीं हो सका (यानी एक स्वतंत्र निर्भरता श्रृंखला से)। लेकिन एएमडी सीपीयू पर, यह ईएक्स के लिए एक नई निर्भरता श्रृंखला शुरू करेगा।

वैसे भी, मुझे लगता है कि एवीआर एक साधारण सरल क्रम में पाइपलाइन डिजाइन है, इसलिए पुराने पंजीकरण के लिए एक प्रदर्शन भूमि-मेरा होने का कोई तरीका नहीं है जब तक कि कोड (उदाहरण के लिए) इसमें कैश-मिस लोड नहीं होता परिणाम का कभी भी उपयोग नहीं किया। (यहां तक ​​कि इन-आदेश पाइपलाइनों जब तक कुछ परिणाम का उपयोग करता है उच्च विलंबता के संचालन के लिए प्रतीक्षा करने की आवश्यकता नहीं है।)

+0

आपको बहुत बहुत धन्यवाद! मुझे पंजीकरण में -1 प्राप्त करने में परेशानी हो रही थी, मैंने तुलना के बाद एक घटाव-उधार लेने का विचार नहीं किया था; यह चीजों को बेहद साफ करता है। – stealthbomber10

+2

@ stealthbomber10: हाँ, यह साफ जब चाल मैं एक वास्तुकला (x86) से पता (इस उत्तर) दूसरे पर उपयोगी हैं। x86 में निर्देश भी हैं [एक रजिस्टर को 0 या 1 को ध्वज के आधार पर सेट करें] (http://www.felixcloutier.com/x86/SETcc.html), लेकिन वे केवल 8-बिट आंशिक रजिस्टरों पर काम करते हैं, और 0 हैं/1 नहीं 0/-1। (बेशक एक डीईसी निर्देश 0/1 में -1/0 बदल जाता है, यह एक और उपयोगी चाल है)। मेरे पालतू शिखरों में से एक यह है कि एएमडी ने एसईटीसीसी को 64-बिट मोड में पूर्ण 32-बिट रजिस्टर लिखने के लिए नहीं बदला (सामान्य अंतर्निहित शून्य-एक्सटेंशन 64 बिट्स के साथ); जो अधिक उपयोगी और कुशल होता। –

+1

@ stealthbomber10: मार्गरेट एक जवाब है कि 'इस्तेमाल किया LSL r24' सीएफ में संकेत बिट पाने के लिए है, तो' ROR r24' इसे वापस डाल करने के लिए तैनात। उसने यह निर्णय लेने के बाद इसे हटा दिया कि यह एक तकनीक के रूप में एक तकनीक के रूप में अच्छा नहीं था, लेकिन यह इस तथ्य का एक अच्छा उदाहरण है कि आमतौर पर ध्वज सेट के लिए कई तरीके हैं। (भले ही इसे एक विशिष्ट ध्वज होना चाहिए, जैसे सी)। –

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