汇编实现多字节乘除法

汇编实现多字节乘除法

乘法

单片机的乘法本质是二进制的乘法,而乘法本身是通过加法实现的。多字节的乘法其实就是移位做加法。例如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
posted @ 2020-10-11 14:54  绿玉杖  阅读(1094)  评论(1编辑  收藏  举报