![](/img/trans.png)
[英]8086 Assembly: Multiply two 16 bit numbers to yield a 32 bit result without using the mul instruction
[英]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
。 你的算法似乎是這樣的:
在每次右移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.