本文介绍了将两个无符号的16位值相乘,而不使用乘法或除法指令[8086汇编]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在做一个分配,在其中编写一个子例程,其中将2个无符号数字相乘并在DX:AX对中产生结果.但是我不能使用mul,imul,div和idiv指令.当我运行代码时,下半部分(AX寄存器)总是正确的,但DX寄存器却不正确.谁能指出我做错了正确的方向?

I'm currently working on an assignment, where I write a subroutine where 2 unsigned numbers get multiplied and yield a result in the DX:AX pair. But i cannot use the instructions mul, imul, div, and idiv. When i run my code, the bottom half (the AX register) is always correct, but the DX register is not. Can anyone point me in the right direction as to what I am doing wrong?

;-----------------------------------------------------------
;
; 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.您的算法似乎是这样的:

You are strangely using di when adding another shifted value of bx. Your algorithm seems to be like this:

  1. 收集值,并将其放入BX和CX中.
  2. 而CX> 0:
  1. Gather values, put them into BX and CX.
  2. While CX>0:
  1. 向右移动CX.
  2. 如果移位后的比特为1,则将BX添加到AX,然后用进位将DI(DI中为零?)添加到DX.
  3. 将BX添加到BX.

  • 返回DX:AX.
  • 在CX每次右移之后,您将丢失DI:BX的左移.当DI保持为零时,您仅移动BX(我将使用shl bx,1而不是add bx,bx),因此,当BX超过16位时,您将丢失应该转到DX的位.要解决此问题,请对DI使用旋转进位.

    You are missing a left-shift of DI:BX after each right shift of CX. You are shifting only BX (and I'd use shl bx,1 instead of add bx,bx) while DI remains at zero, therefore when BX exceeds 16 bits, you lose bits that should go to DX. To remedy, use rotate through carry against 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
    

    这篇关于将两个无符号的16位值相乘,而不使用乘法或除法指令[8086汇编]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    09-17 16:12