2010-06-18 12 views
5

कॉलिंग मैं PIC18 असेंबली में एक सुंदर मूल प्रोग्राम लिख रहा हूं। यह आवश्यक है कि मैं दो 16-बिट संख्याओं को गुणा करने के लिए एक सबराउटिन लिखूं।पीआईसी असेंबली फ़ंक्शन

;*********************************************************************** 
; mul_16bit: subroutine that multiplies two 16 bit numbers stored in 
; addresses mul_16ptr1, mul_16ptr1+1 and mul_16ptr2,mul_16ptr2+1 and 
; returns the 32-bit result in addresses mul_16res1 to mul_16res1+3 

;*********************************************************************** 
mul_16bit: 
      movf mul_16ptr2, W   ;multiply the lower bytes 
      mulwf mul_16ptr1, W 
      movff PRODH, mul_16res+1 
      movff PRODL, mul_16res 
      movf mul_16ptr2+1, W     ;multiply upper bytes 
      mulwf mul_16ptr1+1, W 
      movff PRODH, mul_16res+3 
      movff PRODL, mul_16res+2 
      movf mul_16ptr2, W   ;multiply lower byte of num2 
      mulwf mul_16ptr1+1, W  ; and upper byte of num1 
      movf PRODL, W 
      addwf mul_16res+1, F 
      movf PRODH, W 
      addwfc mul_16res+2, F 
      movlw 0          ; add carry 
      addwfc mul_16res+3, F 
      movf mul_16ptr2+1, W     ;multiply upper byte 
                ;of num1 and lower 
      mulwf mul_16ptr1, W   ; byte of num2 
      movf PRODL, W      ;add the result to mul_16res 
      addwf mul_16res+1, F   ;... 
      movf PRODH, W      ;... 
      addwfc mul_16res+2, F   ;... 
      movlw 0          ; add carry 
      addwfc mul_16res+3, F 
      return 

तरह से मैं अभी लिखा है कि उस में पहली टिप्पणी और उन्हें स्टोर टिप्पणी में 4 रजिस्टरों में में उल्लेख पंजीकृत संग्रहीत नंबर गुणा है: यह है कि मैं क्या अभी है। यह अच्छी तरह से काम करता है अगर मैं केवल एक या दो बार इस गुणा करने की ज़रूरत है, यानी मैं बस की तरह कुछ कह सकते हैं:

mul_16ptr1 set 0x45 
mul_16ptr2 set 0x47 
mul_16res set 0x50 
call   mul_16bit 

0x45 और 0x47 गुणा और 0x50 में संग्रहीत करने के लिए। समस्या तब होती है जब मुझे इसे अलग-अलग डेटा पर एक से अधिक बार कॉल करने की आवश्यकता होती है, क्योंकि असेंबलर मुझे किसी भी पॉइंटर्स को दो बार "सेट" करने नहीं देगा। मैंने अप्रत्यक्ष पहुंच का उपयोग करने की कोशिश की है (यानी मल्टीप्लिकैंड्स और नतीजे को स्टोर करने के लिए एलएफएसआर 1, एलएफएसआर 2, और एलएफएसआर 0 का उपयोग करके) लेकिन फिर मुझे POSTINC0 के इत्यादि की एक बड़ी गड़बड़ी मिलती है। क्या इस फ़ंक्शन को कॉल करने के लिए वैसे भी है?

उत्तर

2

पीआईसी 18 मानदंड के तहत कार्य समर्पित इनपुट चर जैसे रीगा, रेगबी और आरईआरआर का उपयोग करते हैं। तो वहाँ declarated रहे हैं:

RegA res 2 ;16bit var 
ResB res 2 ;16bit var 
ResR res 4 ;32bit var 

कॉलिंग उस तरह का समारोह की तरह दिखता है:

;Constants declaration 
    OperandA set 1234 
    OperandB set 7777 
; 
; 
;Prepare calling operand A 
    movlw low OperandA 
    movwf RegA 
    movlw high OperandA 
    movwf RegA + 1 
;Prepare calling operand B   
    movlw low OperandB 
    movwf RegB + 0 
    movlw high OperandB 
    movwf RegB + 1 
;Function call   
    call MullAB_16bit 
;Result is in RegR 
1

हाँ, पीआईसी विधानसभा भाषा बहुत सी बातें अनावश्यक रूप से जटिल बना देता है।

मुझे लगता है कि आप इसे सीखने के अनुभव के हिस्से के रूप में कर रहे हैं - अन्यथा आप या तो basic math function library जैसे रोजर फ्राउड या फ्रा द्वारा उपयोग करेंगे। थॉमस मैकगाई, या शायद एक उच्च स्तरीय भाषा में स्विच करें जहां उपरोक्त सभी को "*" (बेसिक, सी, पायस्त्र, जेएएल, फर्थ इत्यादि) द्वारा प्रतिस्थापित किया जा सकता है।

कॉलिंग सम्मेलन जीजे का प्रदर्शन बेहद आम है, खासकर पीआईसी 16 से पोर्ट किए गए कोड में, जिसमें केवल एक एफएसआर रजिस्टर था और कोई "PLUSW" रजिस्ट्रार नहीं था।

चूंकि पीआईसी 18 में "PLUSWx" रजिस्ट्रार हैं, इसलिए विभिन्न प्रकार के निसार कॉलिंग सम्मेलनों का उपयोग करना संभव है। क्या R. Reese अनुशंसा करता है कि "पुनः प्रवेश" कोड प्राप्त करने के लिए इसे थोड़ा और अधिक करने का कोई तरीका है?

#include<18f4550> 

OperandA res 2 
OperandB res 2 
Product res 4 

clock_ticks res 2 
useconds_per_clock_tick res 2 
total_time res 4 

    ; example of the "call" part of a possible 3-pointer calling convention. 
    ; Public domain. 
    ; To multiply by some number in Flash or EEPROM, 
    ; first copy them (perhaps using TBLPTR/TABLAT) 
    ; into some convenient temporary Operand buffer in RAM. 
    ; Then: 
    ; WARNING: untested code. 
    ; put pointer to first (least-significant) byte of 16-bit operand A into FSR2 
     BANKSEL FSR0 
     lfsr2 OperandA 
    ; put pointer to first (least-significant) byte of 16-bit operand B into FSR1 
     lfsr1 OperandB 
    ; put pointer to first (least-significant) byte of 32-bit product into FSR0 
     lfsr0 Product 
    ;Function call   
     call mul16x16bit 
    ;Result is in Product 

    ; example of calling the same subroutine with different arguments. 
     BANKSEL FSR0 
     lfsr2 clock_ticks 
     lfsr1 useconds_per_clock_tick 
     lfsr0 total_time 
     call mul16x16bit 
    ; result is in total_time. 
     return 


    ;*********************************************************************** 
    ; mull16x16bit: subroutine that multiplies two 16 bit numbers 
    ; pointed to by the pointer FSR2, FSR2+1, FSR3, FSR3+1, and 
    ; returns the 32-bit result in addresses pointed to by 
    ; FSR0 to FSR0+3. 
    ;*********************************************************************** 
    ; example of a function using a possible 3-pointer calling convention 
    ; WARNING: untested code 
    ; The pointers to operands are: FSR2, FSR1 
    ; The pointer to the result is: FSR0. 
    ; Mostly identical to code in the Microchip PIC18F2550 datasheet, page 98 
    ; Public domain. 

RESULT res 4 // temporary 4 byte register 
TEMP EQU RESULT // temporary 1 byte register 

mul_16bit: 
     movlw 1      ; multiply upper bytes 
     movff PLUSW2, TEMP 
     movf PLUSW1, W 
     mulwf TEMP 
     movff PRODH, RESULT+3 
     movff PRODL, RESULT+2 

     movf INDF2, W    ;multiply the lower bytes 
     mulwf INDF1, W 
     movff PRODH, RESULT+1 
     movff PRODL, RESULT+0 

     movlw 1     ; multiply the high byte of num2 
     movf PLUSW2 
     mulwf INDF1    ; and the low byte of num1 
     movf PRODL, W 
     addwf RESULT+1, F 
     movf PRODH, W 
     addwfc RESULT+2, F 
     movlw 0          ; add carry 
     addwfc RESULT+3, F 

     movlw 1     ; multiply the high byte of num1 
     movf PLUSW1 
     mulwf INDF2    ; and the low byte of num2 
     movf PRODL, W 
     addwf RESULT+1, F 
     movf PRODH, W 
     addwfc RESULT+2, F 
     movlw 0          ; add carry 
     addwfc RESULT+3, F 

     movff RESULT+0, POSTINC0 ; copy result to destination where FSR points. 
     movff RESULT+1, POSTINC0 
     movff RESULT+2, POSTINC0 
     movff RESULT+3, POSTINC0 

     movlw 4 
     subwf FSR0 ; restore original value of FSR0. 

     return 
+0

ठीक है, यदि आप चिप को सस्ते रखना चाहते हैं तो उनमें से कई आवश्यक हैं। –

0

आप इतना है कि वे अपने संकार्य और परिणाम रजिस्टरों पर इशारा करते हुए FSR0-FSR2 साथ समझदारी से व्यवहार करते हैं जाएगा चीजों की व्यवस्था कर सकते हैं? E.G.

 
    movf POSTINC0,w,c 
    mulwf POSTINC1,c  ; Op0L*Op1L (now both point at MSB) 
    movff PRODL,POSTINC2 ; Result0 
    movff PRODH,INDF2 ; Result1 
    mulwf POSTDEC1,c  ; Op0L*Op1H (now 0 points at MSB 1 at LSB) 
    movf PRODL,w,c 
    addwf POSTINC2,f,c ; Result1 (now points at Result2) 
    movlw 0 
    addwfc PRODH,w,c 
    movwf POSTDEC2,c  ; Result2 (now points at Result1) 
    movf INDF0,w,c  ; Op0H 
    mulwf POSTINC1,c  ; Op1L 
    movf PRODL,w,c 
    addwf POSTINC2,f,c ; Result1 
    movf PRODH,w,c 
    addwfc POSTINC2,f,c ; Result2 (carry may be outstanding) 
    clrf INDF2,f,c  ; Result3 
    rlcf POSTDEC2,f,c ; Store carry 
    movf INDF0,w,c  ; Op0H 
    mulwf POSTINC1,c  ; Op1H 
    movf PRODL,w,c 
    addwf POSTINC2,f,c 
    movf PRODH,w,c 
    addwfc INDF2,f,c 

एलएफएसआर बड़ी मात्रा में डेटा के आसपास मैन्युअल रूप से आगे बढ़ने से सस्ता है।

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