home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0000 - 0009 / ibm0000-0009 / ibm0003.tar / ibm0003 / TPOWER53.ZIP / TPASM.ARC / TPBCD.ASM < prev    next >
Encoding:
Assembly Source File  |  1989-07-10  |  17.0 KB  |  596 lines

  1. ;******************************************************
  2. ;           TPBCD.ASM 5.07
  3. ;          Binary Coded Decimal routines
  4. ;     Copyright (c) TurboPower Software 1987.
  5. ; Portions copyright (c) Sunny Hill Software 1985, 1986
  6. ;     and used under license to    TurboPower Software
  7. ;         All rights reserved.
  8. ;******************************************************
  9.  
  10. COMMENT    @
  11.    Format of Turbo 3.x style BCD reals:
  12.    ------------------------------------
  13.    BCD reals are packed    into 10    bytes, as follows:
  14.  
  15.      LSB              MSB (most    significant byte at end)
  16.       |<------ Mantissa    ------>|
  17.     1  2  3  4    5  6  7     8  9 10  <- Byte #
  18.    sE ML ML ML ML ML ML    ML ML ML
  19.     ^                  ^^--- Least significant digit
  20.     |                  |---- Most significant digit
  21.     |
  22.     v
  23.     7 6    5 4 3 2    1 0 <--    Bit # (in Byte 1)
  24.     s E    E E E E    E E
  25.     ^ <--exponent->
  26.     |        |
  27.     |        |--- exponent has offset of    $3F (eg, $41 means 10^2    = 100)
  28.     |----------- sign bit (0 = positive, 1 = negative)
  29.  
  30.    Unpacked BCD    format
  31.    -------------------
  32.    Many    of the routines    that follow work with these reals in an    unpacked
  33.    format. That    is, before an arithmetic operation is performed, the mantissas
  34.    are expanded    (unpacked) so that there is one    digit per byte.    After unpacking,
  35.    the reals look like this:
  36.  
  37.      LSB                        MSB
  38.       |<------------------ mantissa --------------------->|
  39.     1  2  3  4    5  6  7     8  9 10 11 12 13 14 15    16 17 18 19 20
  40.    sE 0d 0d 0d 0d 0d 0d    0d 0d 0d 0d 0d 0d 0d 0d    0d 0d 0d 0d 00
  41.                              ^^
  42.                              ||----    Digit
  43.                              |-----    0
  44.    Byte    1 is unchanged.
  45.    Bytes 2-19 contain the digits in the    mantissa, LSB first. The high
  46.      nibble of each byte is 0, and the low nibble contains the digit.
  47.    Byte    20, sometimes used to keep track of overflow, is set to    0.
  48.  
  49.    When    an operation is    performed on two unpacked BCD's, the result
  50.    ends    up in the second one. This real    is repacked before being moved
  51.    into    a user's variable.
  52. @
  53.  
  54. ;******************************************************    Macros/equates
  55.  
  56.     INCLUDE    TPCOMMON.ASM    ;basic macros/equates
  57.     INCLUDE    TPBCDLOW.ASM    ;shared    macros,    equates, etc. for BCD routines
  58.  
  59. ;******************************************************    Data
  60.  
  61. DATA    SEGMENT    WORD PUBLIC
  62.  
  63. ;Temporary reals in unpacked formats
  64. EXTRN    TempReal1 : BYTE
  65. EXTRN    TempReal2 : BYTE
  66.  
  67. ;Double    length for multiply/divide intermediates
  68. EXTRN    TempReal3 : BYTE
  69.  
  70. ;Half length for transcendental    intermediates
  71. EXTRN    TempReal4 : BYTE
  72. EXTRN    TempReal5 : BYTE
  73. EXTRN    TempReal6 : BYTE
  74.  
  75. ;used by ValBCD
  76. SignMask    DB    ?
  77. ExpSigned    DB    ?
  78. Asciiz        DB    (AsciizLength +1) DUP (?)
  79.  
  80. DATA    ENDS
  81.  
  82. ;******************************************************    Code
  83.  
  84. CODE    SEGMENT    BYTE PUBLIC
  85.  
  86.     ASSUME    CS:CODE,DS:DATA
  87.  
  88.     ;in BCDARITH.ASM
  89.     PUBLIC    AddBCD,    SubBCD,    MultBCD, DivBCD
  90.  
  91.     ;in BCDCOMP.ASM
  92.     PUBLIC    EqualBCD, NotEqualBCD, GreaterBCD, GreaterEqualBCD
  93.     PUBLIC    LessBCD, LessEqualBCD
  94.  
  95.     ;in BCDCONV.ASM
  96.     PUBLIC    LongintToBCD, RoundBCD,    TruncBCD, AbsBCD, IntBCD, FracBCD
  97.     PUBLIC    RealToBCD, BCDtoReal, StrBCD, StrExpBCD, ValBCD
  98.  
  99.     ;routines needed by BCDTRANS
  100.     PUBLIC    LoadTempReal2, CopyTempToTemp, SetUsersReal, ActualIntBCD
  101.     PUBLIC    AddPrimitive, DivPrimitive, MultPrimitive, CopyUsersTo2
  102.  
  103.     ;Routines to call system library STR and VAL procedures
  104.     EXTRN    SystemStr : FAR
  105.     EXTRN    SystemVal : FAR
  106.  
  107. ;Table with powers of ten:
  108.  
  109. Power1    DD    1
  110. Power2    DD    10
  111. Power3    DD    100
  112. Power4    DD    1000
  113. Power5    DD    10000
  114. Power6    DD    100000
  115. Power7    DD    1000000
  116. Power8    DD    10000000
  117. Power9    DD    100000000
  118. Power10    DD    1000000000
  119.  
  120. ;***************************************************** UnpackTempReal
  121.  
  122. ;On entry, DS:SI points    to end of packed real, ES:DI points to end
  123. ;  of unpacked real buffer, direction flag is reset, CX    has MantissaLength
  124. ;On exit, the 9-byte mantissa has been expanded    to 18 bytes (2-19), and
  125. ;  the 20th byte has been initialized to 0.
  126. ;AX, CX, SI, DI    destroyed.
  127.  
  128. UnpackTempReal PROC NEAR
  129.  
  130.     MOV    [DI+1],CH            ;Initialize last byte to 0
  131.     DEC    DI
  132.  
  133. UnpackByte1:
  134.     LODSB                    ;Next byte into    AL
  135.     MOV    AH,AL                ;Store in AH
  136.     AND    AL,LowNibble            ;Isolate LSD in    AL
  137.     SHR    AH,1                ;Isolate MSD in    AH
  138.     SHR    AH,1
  139.     SHR    AH,1
  140.     SHR    AH,1
  141.     STOSW                    ;Store unpacked    digits
  142.     LOOP    UnpackByte1            ;Back for next byte
  143.     RET
  144.  
  145. UnpackTempReal ENDP
  146.  
  147. ;***************************************************** UnpackTempReals
  148.  
  149. ;On entry, DS:SI and DS:DI point to two    10-byte    BCD reals, with    their
  150. ;  mantissas packed into bytes 2-10. (ES = DS)
  151. ;On exit, the 9-byte mantissa of each has been expanded    to 18 bytes (2-19), and
  152. ;  the 20th byte has been initialized to 0.
  153. ;AX, BX, CX, and DX destroyed. SI and DI preserved.
  154.  
  155. UnpackTempReals    PROC NEAR
  156.  
  157.     MOV    BX,SI                ;Save SI in BX
  158.     MOV    DX,DI                ;Save DI in DX
  159.     STD                    ;Go backward
  160.  
  161.     ;unpack    real at    DS:SI
  162.     MOV    CX,MantissaLength        ;CX has    # of bytes in mantissa
  163.     ADD    SI,CX                ;Point to end of first mantissa
  164.     MOV    DI,SI
  165.     ADD    DI,CX                ;Point DI to end of unpacked mantissa
  166.     CALL    UnpackTempReal
  167.  
  168.     ;unpack    real that was at DS:DI
  169.     MOV    CX,MantissaLength        ;CX has    # of bytes in mantissa
  170.     MOV    SI,DX                ;Get second real stored    in DX
  171.     ADD    SI,CX                ;Point to end of packed
  172.     MOV    DI,SI
  173.     ADD    DI,CX                ;Point to end of unpacked
  174.     CALL    UnpackTempReal
  175.  
  176.     MOV    SI,BX                ;Restore SI
  177.     MOV    DI,DX                ;Restore DI
  178.     CLD                    ;Clear direction flag
  179.     RET                    ;Return
  180.  
  181. UnpackTempReals    ENDP
  182.  
  183. ;***************************************************** PackTempReal
  184.  
  185. ;On entry, DS:SI points    to an unpacked BCD real. (ES = DS)
  186. ;On exit, its mantissa has been    packed back into 9 bytes.
  187. ;AX, BX, CX, and DX destroyed. SI preserved.
  188.  
  189. PackTempReal    PROC NEAR
  190.  
  191.     MOV    BX,SI                ;Save SI in BX
  192.     INC    SI                ;Point to mantissa
  193.     MOV    DI,SI                ;Point to output
  194.     CLD                    ;Go forward
  195.     MOV    CX,MantissaLength        ;CX has    # of bytes in mantissa
  196.  
  197. PackByte1:
  198.     LODSW                    ;Load LSD into AL, MSD into AH
  199.     SHL    AH,1                ;Shift MSD to top nibble
  200.     SHL    AH,1
  201.     SHL    AH,1
  202.     SHL    AH,1
  203.     OR    AL,AH                ;Merge LSD into    AL
  204.     STOSB                    ;And store
  205.     LOOP    PackByte1            ;Back for next byte
  206.  
  207.     MOV    SI,BX                ;Restore SI
  208.     RET                    ;Return
  209.  
  210. PackTempReal    ENDP
  211.  
  212. ;******************************************************    CopyUsersTo2
  213. ;Copy Real at [BP+6] to    TempReal2
  214. ;Entry:    ES=DS=DSEG
  215.  
  216. CopyUsersTo2 PROC NEAR
  217.     MOV    BX,DS                ;Save DS
  218.     LDS    SI,DWORD PTR [BP+6]
  219.     CLD
  220.     MOV    DI,Offset TempReal2
  221.     MOV    CX,WordsInBCD
  222.     REP MOVSW
  223.     MOV    DS,BX                ;Restore DS
  224.     RET
  225. CopyUsersTo2 ENDP
  226.  
  227. ;******************************************************    CopyTempToTemp
  228. ;Copy one temp real to another
  229. ;Entry:    ES=DS=DSEG, SI=Source, DI=Destination
  230. ;Exit: SI,DI,CX    destroyed
  231.  
  232. CopyTempToTemp PROC NEAR
  233.  
  234.     CLD
  235.     MOV    CX,WordsInBCD
  236.     REP MOVSW
  237.     RET
  238.  
  239. CopyTempToTemp ENDP
  240.  
  241. ;******************************************************    LoadTempReal2
  242.  
  243. ;On entry, it is assumed that SS:[BP+10] points    to real    to load    into
  244. ;  TempReal2
  245. ;On exit, TempReal2 is loaded
  246.  
  247. LoadTempReal2    PROC NEAR
  248.  
  249.     MOV    BX,DS                ;Save DS
  250.     CLD                    ;Go forward
  251.     MOV    ES,BX                ;ES = DS
  252.     MOV    DI,Offset TempReal2        ;ES:DI => TempReal2
  253.     MOV    CX,WordsInBCD            ;CX = words to move
  254.     LDS    SI,DWORD PTR [BP+10]        ;Point to B2
  255.     REP    MOVSW                ;Move the real
  256.     MOV    DS,BX                ;Restore DS
  257.     RET                    ;Return
  258.  
  259. LoadTempReal2    ENDP
  260.  
  261. ;******************************************************    LoadTempReal1
  262.  
  263. ;On entry, it is assumed that SS:[BP+14] points    to real    to load    into
  264. ;  TempReal1
  265. ;On exit, TempReal1 is loaded
  266.  
  267. LoadTempReal1    PROC NEAR
  268.  
  269.     MOV    BX,DS                ;Save DS
  270.     CLD                    ;Go forward
  271.     MOV    ES,BX                ;ES = DS
  272.     MOV    DI,Offset TempReal1        ;ES:DI => TempReal1
  273.     MOV    CX,WordsInBCD            ;CX = words to move
  274.     LDS    SI,DWORD PTR [BP+14]        ;Point to B2
  275.     REP    MOVSW                ;Move the real
  276.     MOV    DS,BX                ;Restore DS
  277.     RET                    ;Return
  278.  
  279. LoadTempReal1    ENDP
  280.  
  281. ;******************************************************    LoadTempReals
  282.  
  283. ;On entry, it is assumed that SS:[BP+14] points    to one real, and SS:[BP+10] to
  284. ;  another.
  285. ;On exit, these    reals have been    loaded into the    first ten bytes    of TempReal1
  286. ;  and TempReal2, respectively
  287.  
  288. LoadTempReals    PROC NEAR
  289.  
  290.     CALL    LoadTempReal1
  291.     CALL    LoadTempReal2
  292.     RET
  293.  
  294. LoadTempReals    ENDP
  295.  
  296. ;******************************************************    SetUsersReal
  297.  
  298. ;On entry, it is assumed that TempReal2    has the    result of an arithmetic
  299. ;  operation, and that SS:[BP+6] points    to a BCD real. This routine loads
  300. ;  that    real with TempReal2
  301.  
  302. SetUsersReal    PROC NEAR
  303.  
  304.     CLD                    ;Go forward
  305.     PUSH    ES
  306.     MOV    SI,Offset TempReal2        ;DS:SI => TempReal2
  307.     LES    DI,DWORD PTR [BP+6]        ;ES:DI => B3
  308.     MOV    CX,WordsInBCD            ;CX = words to move
  309.     REP    MOVSW                ;Move the real
  310.     POP    ES
  311.     RET                    ;Return
  312.  
  313. SetUsersReal    ENDP
  314.  
  315. ;***************************************************** RoundUnpackedReal
  316.  
  317. ;On entry, DS:DI points    to 19 digit unpacked real, whose first byte is to be
  318. ;  rounded. ES=DS=DSEG and CX has maximum number of digits to round.
  319. ;On exit, same unpacked    real is    rounded
  320. ;  AX, CX, DI destroyed.
  321.  
  322. RoundUnpackedReal PROC NEAR
  323.  
  324.     CMP    BYTE PTR [DI],5            ;Compare to 5
  325.     CMC                    ;Prepare carry flag for    rounding
  326.     JNC    RoundDone            ;Done if less
  327.  
  328.     INC    DI                ;Skip lowest digit
  329.     MOV    CX,MantissaDigits        ;18 digits to check
  330.     CLD
  331.  
  332. RoundNext:
  333.     MOV    AL,[DI]                ;Get next byte
  334.     ADC    AL,0                ;Add just the carry from previous
  335.     AAA                    ;Adjust    for unpacked BCD
  336.     STOSB                    ;Store result
  337.     JNC    RoundDone            ;Done if no carry
  338.     LOOP    RoundNext
  339.     MOV    BYTE PTR [DI],1            ;Set last digit    if we got here
  340.  
  341. RoundDone:
  342.     RET                    ;Return
  343.  
  344. RoundUnpackedReal  ENDP
  345.  
  346. ;******************************************************    ShiftDigitsLeft
  347.  
  348. ;On entry, SI points to    the mantissa that is to    have its digits    shifted
  349. ;  backward, and the direction flag is clear.
  350. ;CX, AX, DI destroyed; SI preserved.
  351.  
  352. ShiftDigitsLeft    PROC NEAR
  353.  
  354.     MOV    AX,SI                ;save SI in AX
  355.     INC    SI                ;SI points to first digit
  356.     MOV    DI,SI                ;DI = SI
  357.     INC    SI                ;SI points to second digit
  358.     MOV    CX,MantissaLength        ;CX has    words to move
  359.     REP    MOVSW                ;Move digits back
  360.     MOV    SI,AX                ;restore SI
  361.     RET                    ;return
  362.  
  363. ShiftDigitsLeft    ENDP
  364.  
  365. ;******************************************************    ShiftDigitsRight
  366.  
  367. ;On entry, SI points to    the mantissa that is to    have its digits    shifted
  368. ;  forward
  369. ;CX, AX, DI destroyed; SI preserved; Direction flag returned forward
  370.  
  371. ShiftDigitsRight PROC NEAR
  372.  
  373.     MOV    AX,SI                ;save SI in AX
  374.     ADD    SI,MantissaDigits-2        ;first word to move
  375.     MOV    DI,SI                ;DI = SI
  376.     INC    DI                ;DI points to last word
  377.     MOV    CX,MantissaLength        ;CX has    words to move
  378.     STD                    ;backward
  379.     REP    MOVSW                ;Move digits
  380.     MOV    SI,AX                ;restore SI
  381.     CLD                    ;forward
  382.     RET                    ;return
  383.  
  384. ShiftDigitsRight ENDP
  385.  
  386. ;******************************************************    AddPrimitive
  387.  
  388. ;On entry, TempReal1 and TempReal2 contain two packed BCD reals    to be added.
  389. ;  Direction flag is clear, ES = DS.
  390. ;On exit, TempReal2 contains the result    in packed BCD format.
  391.  
  392. AddPrimitive    PROC NEAR
  393.  
  394.     MOV    SI,Offset TempReal1        ;DS:SI => TempReal1
  395.     MOV    AH,[SI]                ;AH has    sign/exp of TempReal1
  396.     OR    AH,AH                ;Is it 0?
  397.     JZ    APzeroDone            ;If not, check TempReal2 for 0
  398.  
  399. APchkZero:
  400.     MOV    DI,Offset TempReal2        ;ES:DI and DS:DI => TempReal2
  401.     MOV    AL,[DI]                ;AL has    sign/exp of TempReal2
  402.     OR    AL,AL                ;Is it 0?
  403.     JNZ    APHaveToAdd            ;If not, have to add
  404.     MOV    CX,WordsInBCD            ;CX = words to move
  405.     REP    MOVSW                ;TempReal2 = TempReal1
  406. APzeroDone:
  407.     RET                    ;Return
  408.  
  409. APHaveToAdd:
  410.     PUSH    AX                ;Save AX
  411.     CALL    UnpackTempReals            ;unpack    the mantissas
  412.     POP    AX                ;Restore AX
  413.     SetZero    BL                ;BL = 0
  414.     MOV    [DI],BL                ;Set first byte    of each    to 0
  415.     MOV    [SI],BL
  416.     MOV    BX,AX                ;Save signs/exponents in BX
  417.     AND    BX,ExponentsOnly        ;Clear sign bits
  418.     MOV    DH,AL
  419.     AND    DH,SignBit            ;DH has    sign of    TempReal2
  420.     XOR    AL,AH                ;merge signs/exponents (set SF)
  421.     PUSHF                    ;save flags
  422.     CALL    AcctForExponents        ;adjust    to account for exponents
  423.     MOV    DL,BL                ;DL has    sign/exp of result
  424.     FakePOPF                ;restore flags
  425.     CLC                    ;clear carry flag
  426.     MOV    BX,DI                ;BX points to result's mantissa
  427.     MOV    CX,SigDigits            ;CX has    loop count
  428.     JS    APsubMantissas            ;was SF    was set    when signs/exps
  429.                         ;were merged? if so, subtract
  430.  
  431. APaddMantissas:
  432.     LODSB                    ;AL has    next byte in TempReal1
  433.     ADC    AL,[DI]                ;Add to    the byte in TempReal2
  434.     AAA                    ;Adjust    for addition
  435.     STOSB                    ;Store the result
  436.     LOOP    APaddMantissas            ;Repeat
  437.     JNC    AddNoOV                ;Ready to normalize if carry
  438.                         ;not set
  439.  
  440.     INC    BYTE PTR [DI]            ;increment overflow byte (was 0, now 1)
  441.     INC    DL                ;increment the exponent
  442. AddNoOV:
  443.     MOV    DI,BX
  444.     JMP    SHORT NormalizeMantissa        ;Now normalize the mantissa
  445.  
  446. APsubMantissas:
  447.     LODSB                    ;AL has    next byte in TempReal1
  448.     MOV    AH,AL                ;store in AH
  449.     MOV    AL,[DI]                ;AL has    next byte in TempReal2
  450.     SBB    AL,AH                ;subtract the two
  451.     AAS                    ;account for subtraction
  452.     STOSB                    ;Store the result
  453.     LOOP    APsubMantissas            ;repeat
  454.     MOV    DI,BX                ;restore DI from BX
  455.     JC    APnegate            ;Negate    result if CF set
  456.     JMP    SHORT NormalizeMantissa        ;Normalize the mantissa
  457.  
  458. APnegate:
  459.     CLC                    ;clear carry flag
  460.     MOV    CX,SigDigits            ;CX = #    of significant digits
  461. APnegMantissa:
  462.     MOV    AL,CH                ;AL = 0
  463.     SBB    AL,[DI]                ;AL = -[DI]
  464.     AAS                    ;adjust    for subtraction
  465.     STOSB                    ;store the result
  466.     LOOP    APnegMantissa            ;repeat
  467.     MOV    DI,BX                ;restore DI
  468.     XOR    DH,SignBit            ;flip sign of result and
  469.                         ;normalize mantissa
  470. NormalizeMantissa:
  471.     SetZero    BX                ;exponent delta    = 0
  472.     MOV    SI,DI                ;SI points to result's mantissa
  473.     MOV    AL,[SI+SigDigits]        ;Get value of overflow byte
  474.     OR    AL,AL                ;Is it zero?
  475.     JZ    APCheckMSB            ;If so,    check the the MSB
  476.     INC    DI                ;start with first byte in mantissa
  477.     CALL    RoundUnpackedReal        ;round the result
  478.     CALL    ShiftDigitsLeft            ;and shift digits to the left
  479.     JMP    SHORT APNormalized        ;normalized
  480.  
  481. APCheckMSB:
  482.     MOV    AL,[SI+MantissaDigits]        ;AL has    MSB of mantissa
  483.     OR    AL,AL                ;is MSB    0?
  484.     JZ    APshift                ;if so,    need to    shift
  485.     CALL    RoundUnpackedReal        ;round the result
  486.     JMP    SHORT APNormalized        ;now normalized
  487.  
  488. APshift:
  489.     STD                    ;go backward
  490.     MOV    DI,SI                ;DI = SI
  491.     ADD    DI,MantissaDigits        ;point DI to MSB
  492.     SetZero    AX                ;AX = 0
  493.     MOV    CX,SigDigits            ;scan all 19 significant digits
  494.     REPE    SCASB                ;scan for non-0    bytes
  495.     JZ    APzero                ;all zeros, so set exponent to 0
  496.  
  497.     INC    CX                ;add 1 to get #    of digits before t
  498.                         ;the first 0 (from end)
  499.     INC    DI                ;point DI to first non-0 digit
  500.     PUSH    SI                ;Save SI
  501.     XCHG    SI,DI                ;DI points to mantissa,    SI
  502.                         ;to first non-0    digit
  503.     ADD    DI,MantissaDigits        ;DI points to MSB
  504.     MOV    BX,DI                ;BX points to MSB
  505.     SUB    BX,SI                ;BX = #    of non-zero
  506.     REP    MOVSB                ;move the significant digits
  507.     MOV    CX,BX                ;# of bytes to fill with 0
  508.     REP    STOSB                ;fill with zeros
  509.     POP    SI                ;restore SI
  510.     CLD                    ;Clear direction flag
  511.  
  512. APNormalized:
  513.     CLC                    ;clear carry flag
  514.     ADC    DL,0                ;sets SF if exponent > $7F
  515.     SUB    DL,BL                ;subtract delta    in BL
  516.     JBE    APzero                ;result    is zero    if DL <= BL
  517.     JNS    APok                ;result    OK if SF not set
  518.     STC                    ;else indicate overflow
  519.     CALL    PackTempReal            ;Re-pack the real anyway
  520.     RET                    ;and return
  521.  
  522. APzero:    SetZero    DX                ;DX = 0
  523. APok:    OR    DL,DH                ;set sign bit (stored in DH)
  524.     MOV    [SI],DL                ;set sign/exponent (in DL)
  525.     CLD                    ;Clear direction flag
  526.     CALL    PackTempReal            ;Re-pack the real
  527.     RET                    ;return
  528.  
  529. AddPrimitive    ENDP
  530.  
  531. ;******************************************************    MultPrimitive
  532. ;Actually multiply two BCD numbers
  533. ;Entry:    TempReal1 and TempReal2    loaded with packed reals to multiply
  534. ;Exit: packed result in    TempReal2
  535.  
  536. MultPrimitive PROC NEAR
  537.     MOV    SI,offset TempReal1        ;Point SI to TempReal1
  538.     MOV    DI,offset TempReal2        ;Point DI to TempReal2
  539.  
  540. ;See if    either input is    zero
  541.     XOR    AX,AX
  542.     ADD    AH,[DI]                ;Exponent of TempReal2 in AH
  543.     MOV    [DI],AL                ;Clear exponent    of TempReal2
  544.     JZ    MultPrimDone            ;If zero, we're done
  545.     ADD    AL,[SI]                ;TempReal1 exponent in AL
  546.     JZ    MultPrimDone            ;If zero, we're done
  547.     PUSH    AX                ;Store Exponent/Sign word
  548.     CALL    UnpackTempReals            ;Unpack    the two    inputs
  549.     CALL    MultBcdMant            ;Multiply the mantissas
  550.     POP    AX                ;Restore Exponent/Sign word
  551.     CALL    MultGetExponent            ;Compute exponent and sign
  552.     MOV    SI,offset TempReal2
  553.     CALL    PackTempReal            ;Pack the result
  554. MultPrimDone:                    ;DS:SI points to packed    result
  555.     RET
  556. MultPrimitive ENDP
  557.  
  558. ;********************************************************** DivPrimitive
  559. ;Divide    TempReal2 by TempReal1 and return result in TempReal2
  560. ;Entry:    DS=ES=DSEG
  561.  
  562. DivPrimitive PROC NEAR
  563.     MOV    SI,offset TempReal1        ;Point SI to divisor
  564.     MOV    DI,offset TempReal2        ;Point DI to numerator
  565.     CMP    BYTE PTR [SI],0
  566.     JNZ    DivisorOK
  567.     INT    DivZeroInt            ;Divide    by zero    error
  568.     RET                    ;Return    in case    of error recovery
  569. DivisorOK:
  570.     CMP    BYTE PTR [DI],0            ;Check for zero    numerator
  571.     JZ    DivPrimDone            ;We're done if so
  572.     MOV    AH,[DI]                ;Exponent of Numerator in AH
  573.     MOV    AL,[SI]                ;Divisor exponent in AL
  574.     PUSH    AX                ;Save word for later
  575.     CALL    UnpackTempReals            ;Unpack    the two    inputs
  576.     CALL    DivBcdMant            ;Divide    the mantissas, result in TempReal2
  577.     POP    AX                ;Restore exponent/sign word
  578.     MOV    DI,offset TempReal2        ;Point DI to base of answer
  579.     CALL    DivGetExponent            ;Compute the exponent and sign
  580.     MOV    SI,DI                ;Point SI to base of answer
  581.     CALL    PackTempReal            ;Pack the result
  582. DivPrimDone:
  583.     RET
  584.  
  585. DivPrimitive ENDP
  586.  
  587. ;******************************************************    Includes
  588.  
  589.     INCLUDE    BCDARITH.ASM    ;Basic arithmetic routines
  590.     INCLUDE    BCDCOMP.ASM    ;Real number comparison
  591.     INCLUDE    BCDCONV.ASM    ;Conversion routines
  592.  
  593. CODE    ENDS
  594.  
  595.     END
  596.