home *** CD-ROM | disk | FTP | other *** search
/ Inside Multimedia 1995 July / IMM0795.ISO / share / os2 / pmfract / src / pmgenerl.asm < prev    next >
Assembly Source File  |  1994-01-24  |  19KB  |  668 lines

  1. ;
  2. ;    General routines - FRACTINT for PM version.
  3. ;
  4. ;    Multiply/Divide from WGENERAL.ASM (WINFRACT)
  5. ;    cputype/fputype from GENERAL.ASM (FRACTINT for DOS)
  6. ;    toextra/fromextra/cmpextra from GENERAL.ASM (FRACTINT for DOS)
  7. ;
  8. ;
  9. ;    Generic assembler routines that have very little at all
  10. ;       to do with fractals.
  11. ;
  12. ;       (NOTE:  The video routines have been moved over to VIDEO.ASM)
  13. ;
  14. ;
  15. ; ---- 32-bit Multiply/Divide Routines (includes 16-bit emulation)
  16. ;
  17. ;       multiply()
  18. ;       divide()
  19. ;
  20. ; ---- CPU, FPU Detectors
  21. ;
  22. ;       cputype()
  23. ;    fputype()
  24. ;
  25. ; ---- Quick-copy to/from Extraseg support
  26. ;
  27. ;    toextra()
  28. ;    fromextra()
  29. ;    cmpextra()
  30. ;
  31.  
  32. .MODEL    medium,c
  33.  
  34. .8086
  35.  
  36. .DATA
  37.  
  38.  
  39. ; ************************ Public variables *****************************
  40.  
  41. public        overflow        ; Mul, Div overflow flag: 0 means none
  42.  
  43. ;        arrays declared here, used elsewhere
  44. ;        arrays not used simultaneously are deliberately overlapped
  45.  
  46. public        prefix, suffix, dstack, decoderline ; for the Decoder
  47. public        strlocn, teststring, block    ; used by the Encoder
  48. public        boxx, boxy, boxvalues        ; zoom-box arrays
  49. public        olddacbox            ; temporary DAC saves
  50. public        rlebuf                ; Used ty the TARGA En/Decoder
  51.  
  52. .DATA
  53.  
  54. ; ************************* "Shared" array areas **************************
  55.  
  56. ; Short forms used in subsequent comments:
  57. ;   name........duration of use......................modules....................
  58. ;   encoder    "s"aving an image                    encoder.c
  59. ;   decoder    "r"estoring an image                 decoder.c, gifview.c
  60. ;   zoom    zoom box is visible             zoom.c, video.asm
  61. ;   vidswitch    temp during video mode setting         video.asm
  62. ;   vidreset    temp during video reset          prompts.c, fractint.c, rotate.c, cmdfiles.c
  63. ;   tgaview    restore of tga image             tgaview.c
  64. ;   solidguess    image gen with "g", not to disk      calcfrac.c
  65. ;   btm     image gen with "b", not to disk      calcfrac.c
  66.  
  67. block        label    byte        ; encoder(266)
  68. suffix        dw    2048 dup(0)    ; decoder(4k), vidswitch(256)
  69.  
  70. teststring    label    byte        ; encoder(100)
  71. dstack        dw    2048 dup(0)    ; decoder(4k), solidguess(4k), btm(2k)
  72.                     ;   zoom(2k)
  73.  
  74. strlocn     label    word        ; encoder(10k)
  75. prefix        label    word        ; decoder(8k), solidguess(6k)
  76. olddacbox    label    byte        ; vidreset(768)
  77. boxx        dw    2048 dup(0)    ; zoom(4k), tgaview(4k)
  78. boxy        dw    2048 dup(0)    ; zoom(4k)
  79. boxvalues    label    byte        ; zoom(2k)
  80. decoderline    db    2050 dup(0)    ; decoder(2049), btm(2k)
  81.  
  82. rlebuf        db    258 dup(0)    ; f16.c(258) .tga save/restore?
  83.  
  84. ; Internal Overflow flag
  85.  
  86. overflow    dw    0        ; overflow flag
  87.  
  88. .CODE
  89.  
  90.  
  91. ; =======================================================
  92. ;
  93. ;    32-bit integer multiply routine with an 'n'-bit shift.
  94. ;    Overflow condition returns 0x7fffh with overflow = 1;
  95. ;
  96. ;    long x, y, z, multiply();
  97. ;    int n;
  98. ;
  99. ;    z = multiply(x,y,n)
  100. ;
  101. ;    requires the presence of an external variable, 'cpu'.
  102. ;        'cpu' == 386 if a 386 is present.
  103.  
  104. ;.MODEL  medium,c
  105.  
  106. .8086
  107.  
  108. .DATA
  109.  
  110. temp    dw    5 dup(0)        ; temporary 64-bit result goes here
  111. sign    db    0            ; sign flag goes here
  112.  
  113. .CODE
  114.  
  115. multiply    proc    x:dword, y:dword, n:word
  116.  
  117.     cmp    cpu,386         ; go-fast time?
  118.     jne    slowmultiply        ; no.  yawn...
  119.  
  120. .386                    ; 386-specific code starts here
  121.  
  122.     mov    eax,x            ; load X into EAX
  123.     imul    y            ; do the multiply
  124.     mov    cx,n            ; set up the shift
  125.     cmp    cx,32            ; ugly klooge:    check for 32-bit shift
  126.     jb    short fastm1        ;  < 32 bits:  no problem
  127.     mov    eax,edx         ;  >= 32 bits:    manual shift
  128.     mov    edx,0            ;  ...
  129.     sub    cx,32            ;  ...
  130. fastm1: shrd    eax,edx,cl        ; shift down 'n' bits
  131.     js    fastm3
  132.     sar    edx,cl
  133.     jne    overmf
  134.     shld    edx,eax,16
  135.     ret
  136. fastm3: sar    edx,cl
  137.     inc    edx
  138.     jne    overmf
  139.     shld    edx,eax,16
  140.     ret
  141. overmf:
  142.     mov    ax,0ffffh        ; overflow value
  143.     mov    dx,07fffh        ; overflow value
  144.     mov    overflow,1        ; flag overflow
  145.     ret
  146.  
  147. .8086                    ; 386-specific code ends here
  148.  
  149. slowmultiply:                ; (sigh)  time to do it the hard way...
  150.     push    di
  151.     push    si
  152.  
  153.     mov    ax,0
  154.     mov    temp+4,ax        ; first, zero out the (temporary)
  155.     mov    temp+6,ax        ;  result
  156.     mov    temp+8,ax
  157.  
  158.     mov    bx,word ptr x        ; move X to SI:BX
  159.     mov    si,word ptr x+2        ;  ...
  160.     mov    cx,word ptr y        ; move Y to DI:CX
  161.     mov    di,word ptr y+2        ;  ...
  162.  
  163.     mov    sign,0            ; clear out the sign flag
  164.     cmp    si,0            ; is X negative?
  165.     jge    mults1            ;  nope
  166.     not    sign            ;  yup.  flip signs
  167.     not    bx            ;   ...
  168.     not    si            ;   ...
  169.     stc                ;   ...
  170.     adc    bx,ax            ;   ...
  171.     adc    si,ax            ;   ...
  172. mults1: cmp    di,0            ; is DI:CX negative?
  173.     jge    mults2            ;  nope
  174.     not    sign            ;  yup.  flip signs
  175.     not    cx            ;   ...
  176.     not    di            ;   ...
  177.     stc                ;   ...
  178.     adc    cx,ax            ;   ...
  179.     adc    di,ax            ;   ...
  180. mults2:
  181.  
  182.     mov    ax,bx            ; perform BX x CX
  183.     mul    cx            ;  ...
  184.     mov    temp,ax         ;  results in lowest 32 bits
  185.     mov    temp+2,dx        ;  ...
  186.  
  187.     mov    ax,bx            ; perform BX x DI
  188.     mul    di            ;  ...
  189.     add    temp+2,ax        ;  results in middle 32 bits
  190.     adc    temp+4,dx        ;  ...
  191.     jnc    mults3            ;  carry bit set?
  192.     inc    word ptr temp+6     ;  yup.  overflow
  193. mults3:
  194.  
  195.     mov    ax,si            ; perform SI * CX
  196.     mul    cx            ;  ...
  197.     add    temp+2,ax        ;  results in middle 32 bits
  198.     adc    temp+4,dx        ;  ...
  199.     jnc    mults4            ;  carry bit set?
  200.     inc    word ptr temp+6     ;  yup.  overflow
  201. mults4:
  202.  
  203.     mov    ax,si            ; perform SI * DI
  204.     mul    di            ;  ...
  205.     add    temp+4,ax        ; results in highest 32 bits
  206.     adc    temp+6,dx        ;  ...
  207.  
  208.     mov    cx,n            ; set up for the shift loop
  209.     cmp    cx,24            ; shifting by three bytes or more?
  210.     jl    multc1            ;  nope.  check for something else
  211.     sub    cx,24            ; quick-shift 24 bits
  212.     mov    ax,temp+3        ; load up the registers
  213.     mov    dx,temp+5        ;  ...
  214.     mov    si,temp+7        ;  ...
  215.     mov    bx,0            ;  ...
  216.     jmp    short multc4        ; branch to common code
  217. multc1: cmp    cx,16            ; shifting by two bytes or more?
  218.     jl    multc2            ;  nope.  check for something else
  219.     sub    cx,16            ; quick-shift 16 bits
  220.     mov    ax,temp+2        ; load up the registers
  221.     mov    dx,temp+4        ;  ...
  222.     mov    si,temp+6        ;  ...
  223.     mov    bx,0            ;  ...
  224.     jmp    short multc4        ; branch to common code
  225. multc2: cmp    cx,8            ; shifting by one byte or more?
  226.     jl    multc3            ;  nope.  check for something else
  227.     sub    cx,8            ; quick-shift 8 bits
  228.     mov    ax,temp+1        ; load up the registers
  229.     mov    dx,temp+3        ;  ...
  230.     mov    si,temp+5        ;  ...
  231.     mov    bx,temp+7        ;  ...
  232.     jmp    short multc4        ; branch to common code
  233. multc3: mov    ax,temp         ; load up the regs
  234.     mov    dx,temp+2        ;  ...
  235.     mov    si,temp+4        ;  ...
  236.     mov    bx,temp+6        ;  ...
  237. multc4: cmp    cx,0            ; done shifting?
  238.     je    multc5            ;  yup.  bail out
  239.  
  240. multloop:
  241.     shr    bx,1            ; shift down 1 bit, cascading
  242.     rcr    si,1            ;  ...
  243.     rcr    dx,1            ;  ...
  244.     rcr    ax,1            ;  ...
  245.     loop    multloop        ; try the next bit, if any
  246. multc5:
  247.     cmp    si,0            ; overflow time?
  248.     jne    overm1            ; yup.    Bail out.
  249.     cmp    bx,0            ; overflow time?
  250.     jne    overm1            ; yup.    Bail out.
  251.     cmp    dx,0            ; overflow time?
  252.     jl    overm1            ; yup.    Bail out.
  253.  
  254.     cmp    sign,0            ; should we negate the result?
  255.     je    mults5            ;  nope.
  256.     not    ax            ;  yup.  flip signs.
  257.     not    dx            ;   ...
  258.     mov    bx,0            ;   ...
  259.     stc                ;   ...
  260.     adc    ax,bx            ;   ...
  261.     adc    dx,bx            ;   ...
  262. mults5:
  263.     jmp    multiplyreturn
  264.  
  265. overm1:
  266.     mov    ax,0ffffh        ; overflow value
  267.     mov    dx,07fffh        ; overflow value
  268.     mov    overflow,1        ; flag overflow
  269.  
  270. multiplyreturn:             ; that's all, folks!
  271.     pop    si
  272.     pop    di
  273.     ret
  274. multiply    endp
  275.  
  276.  
  277. ; =======================================================
  278. ;
  279. ;    32-bit integer divide routine with an 'n'-bit shift.
  280. ;    Overflow condition returns 0x7fffh with overflow = 1;
  281. ;
  282. ;    long x, y, z, divide();
  283. ;    int n;
  284. ;
  285. ;    z = divide(x,y,n);    /* z = x / y; */
  286. ;
  287. ;    requires the presence of an external variable, 'cpu'.
  288. ;        'cpu' == 386 if a 386 is present.
  289.  
  290.  
  291. .8086
  292.  
  293. divide        proc    x:dword, y:dword, n:word
  294.  
  295.     push    di
  296.     push    si
  297.  
  298.     cmp    cpu,386         ; go-fast time?
  299.     jne    slowdivide        ; no.  yawn...
  300.  
  301. .386                    ; 386-specific code starts here
  302.  
  303.     mov    edx,x            ; load X into EDX (shifts to EDX:EAX)
  304.     mov    ebx,y            ; load Y into EBX
  305.  
  306.     mov    sign,0            ; clear out the sign flag
  307.     cmp    edx,0            ; is X negative?
  308.     jge    short divides1        ;  nope
  309.     not    sign            ;  yup.  flip signs
  310.     neg    edx            ;   ...
  311. divides1:
  312.     cmp    ebx,0            ; is Y negative?
  313.     jge    short divides2        ;  nope
  314.     not    sign            ;  yup.  flip signs
  315.     neg    ebx            ;   ...
  316. divides2:
  317.  
  318.     mov    eax,0            ; clear out the low-order bits
  319.     mov    cx,32            ; set up the shift
  320.     sub    cx,n            ; (for large shift counts - faster)
  321. fastd1: cmp    cx,0            ; done shifting?
  322.     je    fastd2            ; yup.
  323.     shr    edx,1            ; shift one bit
  324.     rcr    eax,1            ;  ...
  325.     loop    fastd1            ; and try again
  326. fastd2:
  327.     cmp    edx,ebx         ; umm, will the divide blow out?
  328.     jae    overd1            ;  yup.  better skip it.
  329.     div    ebx            ; do the divide
  330.     cmp    eax,0            ; did the sign flip?
  331.     jl    overd1            ;  then we overflowed
  332.     cmp    sign,0            ; is the sign reversed?
  333.     je    short divides3        ;  nope
  334.     neg    eax            ; flip the sign
  335. divides3:
  336.     push    eax            ; save the 64-bit result
  337.     pop    ax            ; low-order  16 bits
  338.     pop    dx            ; high-order 16 bits
  339.     jmp    dividereturn        ; back to common code
  340.  
  341. .8086                    ; 386-specific code ends here
  342.  
  343. slowdivide:                ; (sigh)  time to do it the hard way...
  344.  
  345.     mov    ax,word ptr x        ; move X to DX:AX
  346.     mov    dx,word ptr x+2        ;  ...
  347.  
  348.     mov    sign,0            ; clear out the sign flag
  349.     cmp    dx,0            ; is X negative?
  350.     jge    divides4        ;  nope
  351.     not    sign            ;  yup.  flip signs
  352.     not    ax            ;   ...
  353.     not    dx            ;   ...
  354.     stc                ;   ...
  355.     adc    ax,0            ;   ...
  356.     adc    dx,0            ;   ...
  357. divides4:
  358.  
  359.     mov    cx,32            ; get ready to shift the bits
  360.     sub    cx,n            ; (shift down rather than up)
  361.     mov    byte ptr temp+4,cl    ;  ...
  362.  
  363.     mov    cx,0            ;  clear out low bits of DX:AX:CX:BX
  364.     mov    bx,0            ;  ...
  365.  
  366.     cmp    byte ptr temp+4,16    ; >= 16 bits to shift?
  367.     jl    dividex0        ;  nope
  368.     mov    bx,cx            ;  yup.  Take a short-cut
  369.     mov    cx,ax            ;   ...
  370.     mov    ax,dx            ;   ...
  371.     mov    dx,0            ;   ...
  372.     sub    byte ptr temp+4,16    ;   ...
  373. dividex0:
  374.     cmp    byte ptr temp+4,8    ; >= 8 bits to shift?
  375.     jl    dividex1        ;  nope
  376.     mov    bl,bh            ;  yup.  Take a short-cut
  377.     mov    bh,cl            ;   ...
  378.     mov    cl,ch            ;   ...
  379.     mov    ch,al            ;   ...
  380.     mov    al,ah            ;   ...
  381.     mov    ah,dl            ;   ...
  382.     mov    dl,dh            ;   ...
  383.     mov    dh,0            ;   ...
  384.     sub    byte ptr temp+4,8    ;   ...
  385. dividex1:
  386.     cmp    byte ptr temp+4,0    ; are we done yet?
  387.     je    dividex2        ;  yup
  388.     shr    dx,1            ; shift all 64 bits
  389.     rcr    ax,1            ;  ...
  390.     rcr    cx,1            ;  ...
  391.     rcr    bx,1            ;  ...
  392.     dec    byte ptr temp+4     ; decrement the shift counter
  393.     jmp    short dividex1        ;  and try again
  394. dividex2:
  395.  
  396.     mov    di,word ptr y        ; move Y to SI:DI
  397.     mov    si,word ptr y+2        ;  ...
  398.  
  399.     cmp    si,0            ; is Y negative?
  400.     jge    divides5        ;  nope
  401.     not    sign            ;  yup.  flip signs
  402.     not    di            ;   ...
  403.     not    si            ;   ...
  404.     stc                ;   ...
  405.     adc    di,0            ;   ...
  406.     adc    si,0            ;   ...
  407. divides5:
  408.  
  409.     mov    byte ptr temp+4,33    ; main loop counter
  410.     mov    temp,0            ; results in temp
  411.     mov    word ptr temp+2,0    ;  ...
  412.  
  413. dividel1:
  414.     shl    temp,1            ; shift the result up 1
  415.     rcl    word ptr temp+2,1    ;  ...
  416.     cmp    dx,si            ; is DX:AX >= Y?
  417.     jb    dividel3        ;  nope
  418.     ja    dividel2        ;  yup
  419.     cmp    ax,di            ;  maybe
  420.     jb    dividel3        ;  nope
  421. dividel2:
  422.     cmp    byte ptr temp+4,32    ; overflow city?
  423.     jge    overd1            ;  yup.
  424.     sub    ax,di            ; subtract Y
  425.     sbb    dx,si            ;  ...
  426.     inc    temp            ; add 1 to the result
  427.     adc    word ptr temp+2,0    ;  ...
  428. dividel3:
  429.     shl    bx,1            ; shift all 64 bits
  430.     rcl    cx,1            ;  ...
  431.     rcl    ax,1            ;  ...
  432.     rcl    dx,1            ;  ...
  433.     dec    byte ptr temp+4     ; time to quit?
  434.     jnz    dividel1        ;  nope.  try again.
  435.  
  436.     mov    ax,temp         ; copy the result to DX:AX
  437.     mov    dx,word ptr temp+2    ;  ...
  438.     cmp    sign,0            ; should we negate the result?
  439.     je    divides6        ;  nope.
  440.     not    ax            ;  yup.  flip signs.
  441.     not    dx            ;   ...
  442.     mov    bx,0            ;   ...
  443.     stc                ;   ...
  444.     adc    ax,0            ;   ...
  445.     adc    dx,0            ;   ...
  446. divides6:
  447.     jmp    short dividereturn
  448.  
  449. overd1:
  450.     mov    ax,0ffffh        ; overflow value
  451.     mov    dx,07fffh        ; overflow value
  452.     mov    overflow,1        ; flag overflow
  453.  
  454. dividereturn:                ; that's all, folks!
  455.     pop    si
  456.     pop    di
  457.     ret
  458. divide        endp
  459.  
  460. ;===============================================================
  461. ;
  462. ; CPUTYPE.ASM : C-callable functions cputype() and ndptype() adapted
  463. ; by Lee Daniel Crocker from code appearing in the late PC Tech Journal,
  464. ; August 1987 and November 1987.  PC Tech Journal was a Ziff-Davis
  465. ; Publication.  Code herein is copyrighted and used with permission.
  466. ;
  467. ; The function cputype() returns an integer value based on what kind
  468. ; of CPU it found, as follows:
  469. ;
  470. ;       Value   CPU Type
  471. ;       =====   ========
  472. ;       86      8086, 8088, V20, or V30
  473. ;       186     80186 or 80188
  474. ;       286     80286
  475. ;       386     80386 or 80386sx
  476. ;       -286    80286 in protected mode
  477. ;       -386    80386 or 80386sx in protected or 32-bit address mode
  478. ;
  479. ; The function ndptype() returns an integer based on the type of NDP
  480. ; it found, as follows:
  481. ;
  482. ;       Value   NDP Type
  483. ;       =====   ========
  484. ;       0       No NDP found
  485. ;       87      8087
  486. ;       287     80287
  487. ;       387     80387
  488. ;
  489. ; No provisions are made for the 80486 CPU/FPU or Weitek FPA chips.
  490. ;
  491. ; Neither function takes any arguments or affects any external storage,
  492. ; so there should be no memory-model dependencies.
  493.  
  494. ;.model medium, c
  495.  
  496. .DATA
  497. public        cpu,fpu
  498.  
  499.         align    2
  500. cpu        dw    0        ; cpu type: 86, 186, 286, or 386
  501. fpu        dw    0        ; fpu type: 0, 87, 287, 387
  502.  
  503. .286P
  504. .code
  505.  
  506. cputype proc
  507.         push    bp
  508.  
  509.         push    sp                      ; 86/186 will push SP-2;
  510.         pop     ax                      ; 286/386 will push SP.
  511.         cmp     ax, sp
  512.         jz      not86                   ; If equal, SP was pushed
  513.         mov     ax, 186
  514.         mov     cl, 32                  ;   186 uses count mod 32 = 0;
  515.         shl     ax, cl                  ;   86 shifts 32 so ax = 0
  516.         jnz     exit                    ; Non-zero: no shift, so 186
  517.         mov     ax, 86                  ; Zero: shifted out all bits
  518.         jmp     short exit
  519. not86:
  520.         pushf                           ; Test 16 or 32 operand size:
  521.         mov     ax, sp                  ;   Pushed 2 or 4 bytes of flags?
  522.         popf
  523.         inc     ax
  524.         inc     ax
  525.         cmp     ax, sp                  ;   Did pushf change SP by 2?
  526.         jnz     is32bit                 ;   If not, then 4 bytes of flags
  527. is16bit:
  528.         sub     sp, 6                   ; Is it 286 or 386 in 16-bit mode?
  529.         mov     bp, sp                  ; Allocate stack space for GDT pointer
  530.         sgdt    fword ptr [bp]
  531.         add     sp, 4                   ; Discard 2 words of GDT pointer
  532.         pop     ax                      ; Get third word
  533.         inc     ah                      ; 286 stores -1, 386 stores 0 or 1
  534.         jnz     is386
  535. is286:
  536.         mov     ax, 286
  537.         jmp     short testprot          ; Check for protected mode
  538. is32bit:
  539.         db      66h                     ; 16-bit override in 32-bit mode
  540. is386:
  541.         mov     ax, 386
  542. testprot:
  543.         smsw    cx                      ; Protected?  Machine status -> CX
  544.         ror     cx,1                    ; Protection bit -> carry flag
  545.         jnc     exit                    ; Real mode if no carry
  546.         neg     ax                      ; Protected:  return neg value
  547. exit:
  548.         pop     bp
  549.         ret
  550. cputype endp
  551.  
  552. .data
  553.  
  554. control dw      0                       ; Temp storage for 8087 control
  555.                                         ;   and status registers
  556. .code
  557.  
  558. fputype proc
  559.         push    bp
  560.  
  561.         fninit                          ; Defaults to 64-bit mantissa
  562.         mov     byte ptr control+1, 0
  563.         fnstcw  control                 ; Store control word over 0
  564. ;       dw      3ed9h                   ; (klooge to avoid the MASM \e switch)
  565. ;       dw      offset control          ; ((equates to the above 'fnstcw' cmd))
  566.         mov     ah, byte ptr control+1  ; Test contents of byte written
  567.         cmp     ah, 03h                 ; Test for 64-bit precision flags
  568.         je      gotone                  ; Got one!  Now let's find which
  569.         xor     ax, ax
  570.         jmp     short fexit             ; No NDP found
  571. gotone:
  572.         and     control, not 0080h      ; IEM = 0 (interrupts on)
  573.         fldcw   control
  574.         fdisi                           ; Disable ints; 287/387 will ignore
  575.         fstcw   control
  576.         test    control, 0080h
  577.         jz      not87                   ; Got 287/387; keep testing
  578.         mov     ax, 87
  579.         jmp     short fexit
  580. not87:
  581.         finit
  582.         fld1
  583.         fldz
  584.         fdiv                            ; Divide 1/0 to create infinity
  585.         fld     st
  586.         fchs                            ; Push -infinity on stack
  587.         fcompp                          ; Compare +-infinity
  588.         fstsw   control
  589.         mov     ax, control
  590.         sahf
  591.         jnz     got387                  ; 387 will compare correctly
  592.         mov     ax, 287
  593.         jmp     short fexit
  594. got387:                                 ; Only one left (until 487/Weitek
  595.         mov     ax, 387                 ;   test is added)
  596. fexit:
  597.         pop     bp
  598.         ret
  599. fputype endp
  600.  
  601. .DATA
  602. public        extraseg
  603.  
  604. extraseg    dw    0        ; extra 64K segment (allocated by init)
  605.  
  606. .CODE
  607.  
  608. ; *************** Function toextra(tooffset,fromaddr, fromcount) *********
  609.  
  610. toextra proc    uses es di si, tooffset:word, fromaddr:word, fromcount:word
  611.     cmp    extraseg,0        ; IS there extra memory?
  612.     je    tobad            ;  nope.  too bad.
  613.     cld                ; move forward
  614.     mov    ax,extraseg        ; load ES == extra segment
  615.     mov    es,ax            ;  ..
  616.     mov    di,tooffset        ; load to here
  617.     mov    si,fromaddr        ; load from here
  618.     mov    cx,fromcount        ; this many bytes
  619.     rep    movsb            ; do it.
  620. tobad:
  621.     ret                ; we done.
  622. toextra endp
  623.  
  624.  
  625. ; *************** Function fromextra(fromoffset, toaddr, tocount) *********
  626.  
  627. fromextra proc    uses es di si, fromoffset:word, toaddr:word, tocount:word
  628.     push    ds            ; save DS for a tad
  629.     pop    es            ; restore it to ES
  630.     cmp    extraseg,0        ; IS there extra memory?
  631.     je    frombad         ;  nope.  too bad.
  632.     cld                ; move forward
  633.     mov    si,fromoffset        ; load from here
  634.     mov    di,toaddr        ; load to here
  635.     mov    cx,tocount        ; this many bytes
  636.     mov    ax,extraseg        ; load DS == extra segment
  637.     mov    ds,ax            ;  ..
  638.     rep    movsb            ; do it.
  639. frombad:
  640.     push    es            ; save ES again.
  641.     pop    ds            ; restore DS
  642.     ret                ; we done.
  643. fromextra endp
  644.  
  645.  
  646. ; *************** Function cmpextra(cmpoffset,cmpaddr, cmpcount) *********
  647.  
  648. cmpextra proc    uses es di si, cmpoffset:word, cmpaddr:word, cmpcount:word
  649.     cmp    extraseg,0        ; IS there extra memory?
  650.     je    cmpbad            ;  nope.  too bad.
  651.     cld                ; move forward
  652.     mov    ax,extraseg        ; load ES == extra segment
  653.     mov    es,ax            ;  ..
  654.     mov    di,cmpoffset        ; load to here
  655.     mov    si,cmpaddr        ; load from here
  656.     mov    cx,cmpcount        ; this many bytes
  657.     repe    cmpsb            ; do it.   ****** DPE MASM 6.00 *****
  658.     jnz    cmpbad            ; failed.
  659.     mov    ax,0            ; 0 == true
  660.     jmp    cmpend
  661. cmpbad:
  662.     mov    ax,1            ; 1 == false
  663. cmpend:
  664.     ret                ; we done.
  665. cmpextra    endp
  666.  
  667.     end
  668.