111 lines
2.7 KiB
NASM
111 lines
2.7 KiB
NASM
|
Title Muldiv - (A*B)/C With Correct Rounding
|
||
|
%out MulDiv
|
||
|
page ,132
|
||
|
;----------------------------Module-Header------------------------------;
|
||
|
; Module Name: muldiv.asm
|
||
|
;
|
||
|
; (w * Numer) / Denom with correct rounding.
|
||
|
;
|
||
|
; Created:
|
||
|
; Author:
|
||
|
;
|
||
|
; Copyright (c) 1985, 1986, 1987 Microsoft Corporation
|
||
|
;
|
||
|
; MulDiv(w, Numer, Denom) returns (w * Numer) / Denom rounded to the nearest
|
||
|
; integer. A check is made so that division by zero is not attempted.
|
||
|
;-----------------------------------------------------------------------;
|
||
|
|
||
|
|
||
|
.xlist
|
||
|
include cmacros.inc
|
||
|
; include gditype.inc
|
||
|
.list
|
||
|
|
||
|
|
||
|
sBegin code
|
||
|
assumes cs,code
|
||
|
|
||
|
;--------------------------Public-Routine-------------------------------;
|
||
|
; short FAR PASCAL MulDiv(short, short, short)
|
||
|
; short w;
|
||
|
; short Numer;
|
||
|
; short Denom;
|
||
|
;
|
||
|
; (w * Numer)/ Denom with correct rounding.
|
||
|
;
|
||
|
; Returns: AX = result.
|
||
|
; DX = 1 if no overflow.
|
||
|
; DX = 0 if overflow.
|
||
|
;
|
||
|
; Preserves: BX,CX
|
||
|
; Doesn't lose: SI,DI,ES,DS
|
||
|
;
|
||
|
; Warnings:
|
||
|
;
|
||
|
; Effects:
|
||
|
;
|
||
|
; History:
|
||
|
; Mon 22-Dec-1986 17:08:55 -by- Kent Settle [kentse]
|
||
|
; Added headers and comments.
|
||
|
;-----------------------------------------------------------------------;
|
||
|
|
||
|
cProc MulDiv,<FAR,PUBLIC>,<bx,cx>
|
||
|
|
||
|
parmW <w, Numer, Denom>
|
||
|
|
||
|
cBegin MulDiv
|
||
|
|
||
|
mov bx,Denom ; get the demoninator
|
||
|
mov cx,bx ; CX holds the final sign
|
||
|
or bx,bx ; ensure the denominator is positive
|
||
|
jns md1
|
||
|
neg bx
|
||
|
|
||
|
md1:
|
||
|
mov ax,w ; get the word we are multiplying
|
||
|
xor cx,ax ; make CX reflect any sign change
|
||
|
or ax,ax ; ensure this word is positive
|
||
|
jns md2
|
||
|
neg ax
|
||
|
|
||
|
md2:
|
||
|
mov dx,Numer ; get the numerator
|
||
|
xor cx,dx ; make CX reflect any sign change
|
||
|
or dx,dx ; ensure the numerator is positive
|
||
|
jns md3
|
||
|
neg dx
|
||
|
|
||
|
md3:
|
||
|
mul dx ; multiply
|
||
|
mov cl,bl ; get half of the demoninator to adjust for rounding
|
||
|
sar bx,1
|
||
|
add ax,bx ; adjust for possible rounding error
|
||
|
adc dx,0 ; this is really a long addition
|
||
|
sal bx,1 ; restore the demoninator
|
||
|
or bl,cl
|
||
|
cmp dx,bx ; check for overflow
|
||
|
jae md5 ; (ae handles /0 case)
|
||
|
div bx ; divide
|
||
|
or ax,ax ; If sign is set, then overflow occured
|
||
|
js md5 ; Overflow.
|
||
|
or cx,cx ; put the sign on the result
|
||
|
jns md4
|
||
|
neg ax
|
||
|
md4:
|
||
|
mov dx,1 ; indicate no overflow.
|
||
|
md6:
|
||
|
|
||
|
cEnd MulDiv
|
||
|
|
||
|
|
||
|
md5:
|
||
|
xor dx,dx ; indicate overflow.
|
||
|
mov ax,7FFFh ; return the largest integer
|
||
|
or cx,cx ; with the correct sign
|
||
|
jns md6
|
||
|
not ax
|
||
|
jmp md6
|
||
|
|
||
|
sEnd code
|
||
|
end
|