Да, язык ассемблера PIC усложняет многие вещи.
Я предполагаю, что вы делаете это как часть опыта обучения - в противном случае вы либо использовали бы базовую библиотеку математических функций например, Роджера Фрауда или о.Thomas McGahee или, возможно, перейти на язык более высокого уровня, где все вышеперечисленное можно заменить на «*» (BASIC, C, Pyastra, JAL, Forth и т. Д.).
Соглашение о вызовах, которое демонстрирует GJочень часто встречается, особенно в коде, перенесенном из PIC16, у которого был только один регистр FSR и нет регистров «PLUSW».
Поскольку PIC18 имеет регистры «PLUSWx», можно использовать различные более подходящие соглашения о вызовах.Есть ли способ немного подправить это, чтобы получить «реентрантный» код, который R.Риз рекомендует?
#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