windows-nt/Source/XPSP1/NT/base/mvdm/wow16/gdi/muldiv.asm

111 lines
2.7 KiB
NASM
Raw Normal View History

2020-09-26 03:20:57 -05:00
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