簡體   English   中英

將兩個無符號16位值相乘,而不使用乘法或除法指令[8086匯編]

[英]Multiply two unsigned 16 bit values, without using multiply or divide instructions [8086 Assembly]

我正在進行一項任務,在那里我寫了一個子程序,其中2個無符號數被乘以並在DX:AX對中產生結果。 但我不能使用mul,imul,div和idiv的指令。 當我運行我的代碼時,下半部分(AX寄存器)總是正確的,但DX寄存器不是。 任何人都可以指出我正確的方向,我做錯了什么?

;-----------------------------------------------------------
;
; Program:  MULTIPLY
;
; Function: Multiplies two 16 bit unsigned values ...
;           .... duplicating the MUL instruction
;
; Input:    The two values to be multiplied are passed on the stack
;           The code conforms to the C/C++ calling sequence
;
; Output:   The 32 bit result is returned in the dx:ax pair
;           Registers required by C/C++ need to be saved and restored
;
; Owner:    Andrew F.
;
; Changes:  Date        Reason
;           ------------------
;           07/20/2013  Original version
;
;
;---------------------------------------
         .model    small
         .8086
         public    _multiply

         .data
;---------------------------------------
; Multiply data
;---------------------------------------


         .code
;---------------------------------------
; Multiply code
;---------------------------------------
_multiply:                             
         push      bp                  ; save bp
         mov       bp,sp               ; anchor bp into the stack
         mov       ax,[bp+4]           ; load multiplicand from the stack
         mov       dx,[bp+6]           ; load multiplier   from the stack

    push    bx
    push    cx
    push    di
;---------------------------------------
; copy ax to cx, and dx to bx
;---------------------------------------  
    mov cx,ax       ;using bx and cx as my inputs
    mov bx,dx
;---------------------------------------
; Check for zeros, zero out ax and dx
;---------------------------------------  
start:
    xor   ax,ax         ; check for multiplication by zero
    mov   dx,ax         ; and zero out ax and dx
    mov   di,cx     ; 
    or    di,bx         ; 
    jz    done      ;
    mov   di,ax         ; DI used for reg,reg adc
;---------------------------------------
; loop / multiply algorithm
;---------------------------------------  
loopp:
    shr   cx,1          ; divide by two, bottom bit moved to carry flag
    jnc   skipAddToResult   ;no carry -> just add to result
    add   ax,bx     ;add bx to ax 
    adc   dx,di         ;add the carry to dx

skipAddToResult:
    add   bx,bx         ;double bx current value
    or    cx,cx         ; zero check
    jnz   loopp     ; if cx isnt zero, loop again


;---------------------------------------
; Restore register values, return
;---------------------------------------  
done:
     pop       di           ;restore di
     pop       cx           ;restore cx
     pop       bx           ;restore bx

         pop       bp                  ; restore bp
         ret                           ; return with result in dx:ax
                                       ;
         end                           ; end source code
;---------------------------------------

在添加另一個bx移位值時,你很奇怪地使用di 你的算法似乎是這樣的:

  1. 收集值,將它們放入BX和CX。
  2. 當CX> 0時:
    1. 向右移動CX。
    2. 如果移位位有1,則將BX添加到AX並將DI(在DI中為零?)添加到帶有進位的DX。
    3. 將BX添加到BX。
  3. 返回DX:AX。

在每次右移CX后,您都錯過了DI:BX的左移。 您正在僅移位BX(我使用shl bx,1而不是add bx,bx )而DI保持為零,因此當BX超過16位時,您將丟失應該轉到DX的位。 為了補救,使用旋轉通過DI進行。

loopp:
    shr   cx,1          ; divide by two, bottom bit moved to carry flag
    jnc   skipAddToResult   ;no carry -> just add to result
    add   ax,bx     ;add bx to ax 
    adc   dx,di         ;add the carry to dx

skipAddToResult:
    shl   bx,1         ;double bx current value
    rcl   di,1         ; and put overflow bits to DI
                       ; this together doubles the number in DI:BX
    or    cx,cx         ; zero check
    jnz   loopp     ; if cx isnt zero, loop again

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM