问题描述
我目前正在做一个分配,在其中编写一个子例程,其中将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:
- 收集值,并将其放入BX和CX中.
- 而CX> 0:
- Gather values, put them into BX and CX.
- While CX>0:
- 向右移动CX.
- 如果移位后的比特为1,则将BX添加到AX,然后用进位将DI(DI中为零?)添加到DX.
- 将BX添加到BX.
在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汇编]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!