汇编实现多字节乘除法
乘法
单片机的乘法本质是二进制的乘法,而乘法本身是通过加法实现的。多字节的乘法其实就是移位做加法。例如7x11,用二进制竖式表示如下图:
可以看到,其实就是判断乘数的每一位是1还是0,如果是1,则将被乘数左移相应的位数,最后相加即可得到乘积。
程序中可以将左移变为右移,进一步精简代码。
以下代码使用PIC单片机的汇编指令实现。
;*******************************************************************************
; * 函数名称: math_multiply
; * 说 明: 三字节乘三字节。
; * 中间变量: ax/bx/cx/mathcnt
; * 输入参数: ax/bx, 乘数
; * 输出参数: bx|ax, 积
;*******************************************************************************
math_multiply:
nop1
movf bx + 2,0,0
movwf cx + 2,0
movf bx + 1,0,0
movwf cx + 1,0
movf bx + 0,0,0
movwf cx + 0,0
clrf bx + 2,0
clrf bx + 1,0
clrf bx + 0,0
movlw .24 ;24次移位
movwf mathcnt,0
math_multiply_loop:
bcf STATUS,C,0
btss ax + 0,0,0
bra math_multiply_loop_next
movf cx + 0,0,0
addn bx + 0,1,0
movf cx + 1,0,0
addc bx + 1,1,0
movf cx + 2,0,0
addc bx + 2,1,0
math_multiply_loop_next:
rrfc bx + 2,1,0
rrfc bx + 1,1,0
rrfc bx + 0,1,0
rrfc ax + 2,1,0
rrfc ax + 1,1,0
rrfc ax + 0,1,0
decsz mathcnt,1,0
bra math_multiply_loop
ret
除法
二进制的除法和十进制的除法原理相同,都是从被除数的高位到低位不断试商的过程。例如11/2,用二进制竖式表示如下图:
;*******************************************************************************
; * 函数名称: math_division
; * 说 明: 六字节除以三字节
; * 中间变量: ax/bx/cx/dx/mathcnt
; * 输入参数: bx|ax, 被除数
; * 输入参数: cx, 除数
; * 输出参数: bx|ax, 商
; * 输出参数: dx, 余数
;*******************************************************************************
math_division:
clrf dx + 2,0
clrf dx + 1,0
clrf dx + 0,0
movlw .48 ;48次移位
movwf mathcnt,0
math_division_loop:
bcf STATUS,C,0 ;最低位先置0
rlfc ax + 0,1,0 ;被除数高位移出到dx
rlfc ax + 1,1,0
rlfc ax + 2,1,0
rlfc bx + 0,1,0
rlfc bx + 1,1,0
rlfc bx + 2,1,0
rlfc dx + 0,1,0
rlfc dx + 1,1,0
rlfc dx + 2,1,0
movf cx + 0,0,0 ;移出的高位和除数比较
subn dx + 0,0,0
movf cx + 1,0,0
subb dx + 1,0,0
movf cx + 2,0,0
subb dx + 2,0,0
btss STATUS,C,0
bra math_division_less
movwf dx + 2,0
movf cx + 0,0,0
subn dx + 0,1,0
movf cx + 1,0,0
subb dx + 1,1,0
incf ax + 0,1,0 ;最低位置1
math_division_less:
decsz mathcnt,1,0
bra math_division_loop
ret