diff options
Diffstat (limited to 'private/mvdm/wow16/gdi/muldiv.asm')
-rw-r--r-- | private/mvdm/wow16/gdi/muldiv.asm | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/private/mvdm/wow16/gdi/muldiv.asm b/private/mvdm/wow16/gdi/muldiv.asm new file mode 100644 index 000000000..066fd0f8d --- /dev/null +++ b/private/mvdm/wow16/gdi/muldiv.asm @@ -0,0 +1,110 @@ + 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 |