2010-06-18 146 views
5

我在PIC18汇编中编写了一个非常基本的程序。它要求我编写一个子程序来乘以两个16位数字。这就是我现在所拥有的:PIC汇编函数调用

;*********************************************************************** 
; 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 

要乘0x450x47并将其存储在0x50。问题是当我需要在不同的数据上多次调用它时,因为汇编程序不会让我“设置”任何指针两次。我尝试过使用间接访问(即使用LFSR1,LFSR2和LFSR0来存储被乘数和结果),但是后来我只是陷入了一大堆POSTINC0等等。有没有办法让这个函数调用更好的东西?

回答

2

PIC18下的函数通常使用专用输入变量,例如RegA,RegB和RegR。 所以有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

是,PIC汇编语言做很多事情不必要地复杂化。

我假设你这样做是作为学习体验的一部分 - 否则你会使用basic math function library,比如Roger Froud或Fr.的一个。托马斯McGahee,或者也许切换到一个更高级的语言,其中所有上述可以替换为“*”(BASIC,C,Pyastra,JAL,Forth等)。

GJ演示的调用约定非常常见,尤其是从PIC16移植的代码中,只有一个FSR寄存器且没有“PLUSW”寄存器。

由于PIC18具有“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

那么,如果你想保持芯片便宜,其中许多是必要的。 – 2010-08-19 18:41:10

0

您可以安排一些东西,使它们在FSR0-FSR2指向您的操作数和结果寄存器时表现明智吗?例如。

 
    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 

LFSR比手动移动大量数据便宜。