home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / PASCAL / TPL60N19 / ARISOURC / LONGDIV.ASM < prev    next >
Assembly Source File  |  1993-01-25  |  6KB  |  124 lines

  1.  
  2. ; *******************************************************
  3. ; *                                                     *
  4. ; *     Turbo Pascal Runtime Library Version 6.0        *
  5. ; *     Longint Division                                *
  6. ; *                                                     *
  7. ; *     Copyright (C) 1989-1993 Norbert Juffa           *
  8. ; *                                                     *
  9. ; *******************************************************
  10.  
  11.              TITLE   LONGDIV
  12.  
  13.  
  14. CODE         SEGMENT BYTE PUBLIC
  15.  
  16.              ASSUME  CS:CODE
  17.  
  18. ; Externals
  19.  
  20.              EXTRN   HaltError:NEAR
  21.  
  22. ; Publics
  23.  
  24.              PUBLIC  LongDiv
  25.  
  26. ;-------------------------------------------------------------------------------
  27. ; LongDiv divides two LONGINT numbers, the dividend and the divisor, resulting
  28. ; in a quotient and a remainder. The routine checks for an attempted division
  29. ; by zero. In that case, it returns to the error handler with error code C8h.
  30. ;
  31. ; INPUT:     DX:AX     dividend
  32. ;            BX:CX     divisor
  33. ;
  34. ; OUTPUT:    DX:AX     quotient of division of dividend by divisor
  35. ;            BX:CX     remainder of division of dividend by divisor
  36. ;
  37. ; DESTROYS:  AX,BX,CX,DX,SI,DI,Flags
  38. ;-------------------------------------------------------------------------------
  39.  
  40. LongDiv      PROC    FAR
  41.              XOR     DX, BX            ; SF set if quotient negative
  42.              PUSHF                     ; save flag
  43.              XOR     DX, BX            ; dividend negative ?
  44.              PUSHF                     ; SF set if dividend (&remaindr) negative
  45.              JNS     $dividnd_pos      ; no, ->
  46.              NOT     DX                ; negate
  47.              NEG     AX                ;  dividend
  48.              SBB     DX, -1            ;   in DX:AX
  49. $dividnd_pos:OR      BX, BX            ; divisor negative ?
  50.              JNS     $divisor_pos      ; no, ->
  51.              NOT     BX                ; negate
  52.              NEG     CX                ;  divisor
  53.              SBB     BX, -1            ;   in BX:CX
  54. $divisor_pos:JNZ     $big_divisor      ; divisor > 65535
  55.              CMP     DX, CX            ; only one division needed ?
  56.              JB      $one_div          ; yes, one division sufficient
  57.              JCXZ    $zero_divide      ; divisor is zero, error
  58.              DB      087h, 0C3h        ; XCHG    AX, BX            ; save lo-word of dividend in BX
  59.              XCHG    AX, DX            ; get hi-word of dividend, load DX with 0
  60.              DIV     CX                ; hi-word of quotient in AX
  61.              XCHG    AX, BX            ; BX = quot. hi-word, AX = divid. lo-word
  62. $one_div:    DIV     CX                ; AX = quotient lo-word
  63.              MOV     CX, DX            ; CX = remainder lo-word,
  64.              MOV     DX, BX            ; DX = quotient hi-word
  65.              XOR     BX, BX            ; clear remainder hi-word (rem. in BX:CX)
  66.              JMP     $set_sign         ; make signed
  67. $big_divisor:PUSH    DX                ; save
  68.              PUSH    AX                ;  dividend
  69.              MOV     SI, CX            ; save
  70.              MOV     DI, BX            ;  divisor
  71.              OR      BH, BH            ; shift more than 8 bits ?
  72.              JZ      $scale_down       ; no, do bit shifts
  73.              MOV     CL, CH            ; shift
  74.              MOV     CH, BL            ;  divisor
  75.              MOV     BL, BH            ;   and
  76.              XOR     BH, BH            ;    dividend
  77.              MOV     AL, AH            ;     8 bits
  78.              MOV     AH, DL            ;      right
  79.              MOV     DL, DH            ;       each
  80.              MOV     DH, BH            ;
  81. $scale_down: SHR     DX, 1             ; scale
  82.              RCR     AX, 1             ;  divisor
  83.              SHR     BX, 1             ;   and
  84.              RCR     CX, 1             ;    dividend until
  85.              JNZ     $scale_down       ;      divisor < 65536
  86.              DIV     CX                ; compute quotient
  87.              MOV     CX, AX            ; save quotient
  88.              MOV     BX, AX            ; save quotient
  89.              MUL     DI                ; quotient * divisor hi-word
  90.              XCHG    AX, CX            ; save result in CX, get quotient from AX
  91.              MUL     SI                ; quotient * divisor lo-word
  92.              ADD     DX, CX            ; DX:AX = quotient * divisor
  93.              POP     CX                ; get dividend lo-word
  94.              SUB     CX, AX            ; divid. lo-word - (quot.*divisor)lo-word
  95.              MOV     AX, BX            ; get quotient
  96.              POP     BX                ; restore dividend hi-word
  97.              SBB     BX, DX            ;  subtract divisor * quot. from dividend
  98.              JNB     $remaindr_ok      ; ok if remainder > 0
  99.              ADD     CX, SI            ; compute
  100.              ADC     BX, DI            ;  correct remaindr (0.095% of all cases)
  101.              DEC     AX                ; adjust quotient
  102. $remaindr_ok:XOR     DX, DX            ; clear hi-word of quotient (AX ≤ 7FFFh)
  103. $set_sign:   POPF                      ; remainder negative ?
  104.              JNS     $pos_remaind      ; no, ->
  105.              NOT     BX                ; negate
  106.              NEG     CX                ;  remainder
  107.              SBB     BX, -1            ;   in BX:CX
  108. $pos_remaind:POPF                      ; result negative ?
  109.              JNS     $pos_result       ; no, ->
  110.              NOT     DX                ; negate
  111.              NEG     AX                ;  quotient
  112.              SBB     DX, -1            ;   in DX:AX
  113. $pos_result: RET                       ; done, return & pop arguments
  114. $zero_divide:ADD     SP, 4             ; remove saved flags from stack
  115.              MOV     AX, 0C8H          ; load error code 200, "division by zero"
  116.              JMP     HaltError         ; execute error handler
  117. LongDiv      ENDP
  118.  
  119.              ALIGN   4
  120.  
  121. CODE         ENDS
  122.  
  123.              END
  124.