Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
2.7 KiB

  1. Title Muldiv - (A*B)/C With Correct Rounding
  2. %out MulDiv
  3. page ,132
  4. ;----------------------------Module-Header------------------------------;
  5. ; Module Name: muldiv.asm
  6. ;
  7. ; (w * Numer) / Denom with correct rounding.
  8. ;
  9. ; Created:
  10. ; Author:
  11. ;
  12. ; Copyright (c) 1985, 1986, 1987 Microsoft Corporation
  13. ;
  14. ; MulDiv(w, Numer, Denom) returns (w * Numer) / Denom rounded to the nearest
  15. ; integer. A check is made so that division by zero is not attempted.
  16. ;-----------------------------------------------------------------------;
  17. .xlist
  18. include cmacros.inc
  19. ; include gditype.inc
  20. .list
  21. sBegin code
  22. assumes cs,code
  23. ;--------------------------Public-Routine-------------------------------;
  24. ; short FAR PASCAL MulDiv(short, short, short)
  25. ; short w;
  26. ; short Numer;
  27. ; short Denom;
  28. ;
  29. ; (w * Numer)/ Denom with correct rounding.
  30. ;
  31. ; Returns: AX = result.
  32. ; DX = 1 if no overflow.
  33. ; DX = 0 if overflow.
  34. ;
  35. ; Preserves: BX,CX
  36. ; Doesn't lose: SI,DI,ES,DS
  37. ;
  38. ; Warnings:
  39. ;
  40. ; Effects:
  41. ;
  42. ; History:
  43. ; Mon 22-Dec-1986 17:08:55 -by- Kent Settle [kentse]
  44. ; Added headers and comments.
  45. ;-----------------------------------------------------------------------;
  46. cProc MulDiv,<FAR,PUBLIC>,<bx,cx>
  47. parmW <w, Numer, Denom>
  48. cBegin MulDiv
  49. mov bx,Denom ; get the demoninator
  50. mov cx,bx ; CX holds the final sign
  51. or bx,bx ; ensure the denominator is positive
  52. jns md1
  53. neg bx
  54. md1:
  55. mov ax,w ; get the word we are multiplying
  56. xor cx,ax ; make CX reflect any sign change
  57. or ax,ax ; ensure this word is positive
  58. jns md2
  59. neg ax
  60. md2:
  61. mov dx,Numer ; get the numerator
  62. xor cx,dx ; make CX reflect any sign change
  63. or dx,dx ; ensure the numerator is positive
  64. jns md3
  65. neg dx
  66. md3:
  67. mul dx ; multiply
  68. mov cl,bl ; get half of the demoninator to adjust for rounding
  69. sar bx,1
  70. add ax,bx ; adjust for possible rounding error
  71. adc dx,0 ; this is really a long addition
  72. sal bx,1 ; restore the demoninator
  73. or bl,cl
  74. cmp dx,bx ; check for overflow
  75. jae md5 ; (ae handles /0 case)
  76. div bx ; divide
  77. or ax,ax ; If sign is set, then overflow occured
  78. js md5 ; Overflow.
  79. or cx,cx ; put the sign on the result
  80. jns md4
  81. neg ax
  82. md4:
  83. mov dx,1 ; indicate no overflow.
  84. md6:
  85. cEnd MulDiv
  86. md5:
  87. xor dx,dx ; indicate overflow.
  88. mov ax,7FFFh ; return the largest integer
  89. or cx,cx ; with the correct sign
  90. jns md6
  91. not ax
  92. jmp md6
  93. sEnd code
  94. end