home *** CD-ROM | disk | FTP | other *** search
/ Deathday Collection / dday.bin / edit / dfe / swapa.asm < prev    next >
Assembly Source File  |  1994-05-02  |  27KB  |  711 lines

  1. ;**************************************************************************;
  2. ;*                           S W A P A . A S M                            *;
  3. ;*------------------------------------------------------------------------*;
  4. ;*    Task           : Assembler module for the SWAP unit                 *;
  5. ;*------------------------------------------------------------------------*;
  6. ;*    Author         : MICHAEL TISCHER                                    *;
  7. ;*    developed on   :  06/01/1989                                        *;
  8. ;*    last update    :  02/28/1990                                        *;
  9. ;*------------------------------------------------------------------------*;
  10. ;*    assembly       : TASM - /MX SWAPA                              *;
  11. ;*                     ... bind to the SWAP unit                          *;
  12. ;**************************************************************************;
  13.  
  14. ;== Constants ===============================================================
  15.  
  16. STACK_LEN  equ 64                 ;Number of words in the internal stack
  17.  
  18. ;== Structures =============================================================
  19.  
  20. ExecStruc struc                   ;Data structure for EXEC function
  21. EsSegEnv  dw ?                    ;Segment address of environment blocks
  22. EsCmdPAdr dd ?                    ;Pointer to command line parameters
  23. EsFCB1Adr dd ?                    ;Pointer to FCB #1
  24. EsFCB2Adr dd ?                    ;Pointer to FCB #2
  25.  
  26. ExecStruc ends
  27.  
  28. public     SwapOutAndExec         ;Gives a Turbo Pascal program the
  29.                                              ;ability to pass the address of
  30.                                              ;the assembler handler
  31. public     InitSwapa              ;Initialization procedure
  32.  
  33. ;== Data segment ===========================================================
  34.  
  35. DATA   segment word public
  36.  
  37. extrn  PrefixSeg : word           ;Segment address of PSP in Turbo variables
  38.  
  39. DATA   ends
  40.  
  41. ;== Program ===============================================================
  42.  
  43. CODE       segment byte public    ;Program segment
  44.  
  45.  
  46. ;== Variables in code segment ===============================================
  47.  
  48. CodeStart  equ this word          ;Code begins here which is copied to
  49.                                              ;the Turbo program
  50.  
  51. ;-- Variables needed by the Swap routines for uploading and downloading ----
  52.  
  53. CoStAddr   dd ?                   ;Orig. address of PARA(CodeStart)
  54. CoStLen    dw ?                   ;Number of words swapped w/ CoStAddr
  55. StackPtr   dw ?                   ;Gets old stack pointer
  56. StackSeg   dw ?                   ;Gets old stack segment
  57. TurboSeg   dw ?                   ;Segment address - Turbo code segment
  58.  
  59. ;-- Variables needed for program configuration and command execution -------
  60.  
  61. NewStack   dw STACK_LEN dup (?)   ;New stack
  62. EndStack   equ this word          ;End of stack
  63.  
  64. Command    dd ?                   ;Pointer to command
  65. CmdPara    dd ?                   ;Pointer to command line parameters
  66. ToDisk     db ?                   ;True when disk swapping occurs
  67. Handle     dw ?                   ;Disk or EMS handle
  68. Len        dd ?                   ;Number of bytes saved
  69.  
  70. FCB1       db  16 dup ( 0 )       ;FCB #1 for PSP
  71. FCB2       db  16 dup ( 0 )       ;FCB #2 for PSP
  72. CmdBuf     db 128 dup ( 0 )       ;Commands following prg. name
  73. PrgName    db  64 dup ( 0 )       ;Program name
  74. ExecData   ExecStruc < 0, CmdBuf, FCB1, FCB2 >   ;Data structure for EXEC
  75.  
  76. OldPara    dw ?                   ;Number of previously reserved paragraphs
  77. FrameSeg   dw ?                   ;Segment address of EMS page frame
  78. Error_Code db 0                   ;Error code for caller
  79.  
  80. TerMes     db 13,10,13,10
  81.               db "╔═══════════════════════════════════════════════════╗",13,10
  82.               db "║ Done_Swap: Stored Turbo Pascal program could      ║",13,10
  83.               db "║            not be reloaded back into memory.      ║",13,10
  84.               db "║            Program execution terminated!          ║",13,10
  85.               db "╚═══════════════════════════════════════════════════╝"
  86.               db 13,10,13,10,"$"
  87.  
  88. Msg1       db 13,10,13,10
  89.               db "╔════════════════════════════╗",13,10
  90.               db "║ Init_Swap: Swapping out    ║",13,10
  91.               db "╚════════════════════════════╝"
  92.               db 13,10,13,10,"$"
  93.  
  94.  
  95. ;== Procedures =============================================================
  96.  
  97. ;---------------------------------------------------------------------------
  98. ;-- StartSwap : Coordinate swapping of Turbo Pascal program
  99.  
  100. StartSwap  proc far
  101.  
  102.               assume cs:code, ds:nothing
  103.  
  104.               ;-- Store current stack and initialize new stack ----------------
  105.  
  106.               cli                    ;Suppress interrupts
  107.               mov   StackPtr,sp      ;Mark current stack
  108.               mov   StackSeg,ss
  109.               push  cs               ;Install new stack
  110.               pop   ss
  111.               mov   sp,offset EndStack - 2
  112.               sti                    ;Re-enable interrupts
  113.  
  114.               push  cs               ;Set DS to CS
  115.               pop   ds
  116.               assume cs:code, ds:code
  117.  
  118.               ;-- Overwrite unnecessary memory --------------------------------
  119.  
  120.               cmp   ToDisk,0         ;Write to EMS memory?
  121.               je    Ems              ;Yes ---> Ems
  122.  
  123.               call  Write2File       ;No ---> Write to file
  124.               jnc   ShrinkMem        ;No error ---> ShrinkMem
  125.  
  126.               mov   Error_Code, 1    ;File output error?
  127.               jmp   short GetBack    ;return to Turbo
  128.  
  129. Ems:       mov   ah,41h           ;Pass segment address of the page frame
  130.               int   67h              ;Call EMM
  131.               mov   FrameSeg,bx      ;Place result in variables
  132.  
  133.               call  Write2Ems        ;Write program to EMS
  134.  
  135.               ;-- Provide number of currently allocated paragraphs ------------
  136.  
  137. ShrinkMem: mov   ax,TurboSeg      ;Segment address of Turbo code segment
  138.               sub   ax,11h           ;Allocate 10 paragraphs for PSP and 1
  139.                                              ;for MCB
  140.               mov   es,ax            ;ES now pointer to Turbo prog. MCB
  141.               mov   bx,es:[3]        ;Get number of paragraphs allocated
  142.               mov   OldPara,bx       ;and place in variable
  143.  
  144.               ;-- Calculate the number of paragraphs needed and reduce  --
  145.               ;-- memory requirements by this amount                    --
  146.  
  147.               inc   ax               ;AX now points to the PSP
  148.               mov   es,ax            ;for function call to ES
  149.               mov   bx,CostLen       ;Number of words needed by Swap routine
  150.               add   bx,128+7         ;Recalculate and round off PSP
  151.               mov   cl,3             ;Divide by 8 words (per paragraph)
  152.               shr   bx,cl
  153.  
  154.               mov   ah,4Ah           ;Function number for "change size"
  155.               int   21h              ;Call DOS interrupt
  156.  
  157.               ;-- Execute specified command line using the EXE function ------
  158.  
  159.               mov   bp,ds            ;Store DS 
  160.  
  161.               mov   ax,cs            ;Set ES and DS to CS
  162.               mov   es,ax
  163.               mov   ds,ax
  164.  
  165.               ;-- Enter segment address of code segments in the pointer -----
  166.               ;-- to the EXEC structure
  167.  
  168.               mov   word ptr ExecData.EsFCB1Adr + 2,ax
  169.               mov   word ptr ExecData.EsFCB1Adr + 2,ax
  170.               mov   word ptr ExecData.EsCmdPAdr + 2,ax
  171.  
  172.               mov   bx,offset ExecData  ;ES:BX point to parameter block
  173.               mov   dx,offset PrgName   ;DS:DX point to command string
  174.  
  175.               mov   ax,4B00h         ;Function number for "EXEC"
  176.               int   21h              ;Call DOS interrupt
  177.               mov   ds,bp            ;Move DS
  178.               jnc   ReMem            ;No error ---> ReMem
  179.  
  180.               mov   Error_Code,ah    ;Note ErrorCode
  181.  
  182.               ;-- Return memory to original size ------------------------------
  183.  
  184. ReMem:     mov   ax,TurboSeg      ;Set Turbo code segment address
  185.               sub   ax,10h           ;to start of PSP
  186.               mov   es,ax            ;and load into ES
  187.               mov   bx,OldPara       ;Old number of paragraphs
  188.  
  189.               mov   ah,4Ah           ;Function number for "change size"
  190.               int   21h              ;Call DOS interrupt
  191.               jnc   GetBack          ;No error ---> GetBack
  192.  
  193.               jmp   Terminate        ;Error in ReMem --> End program
  194.  
  195.               ;-- Return to program -------------------------------------------
  196.  
  197. GetBack:   cmp   ToDisk,0         ;Write to EMS memory?
  198.               je    Ems1             ;Yes ---> Ems1
  199.  
  200.               call  GetFromFile      ;No, reload as file
  201.               jnc   CloseUp          ;No error ---> CloseUp
  202.  
  203.               jmp   Terminate        ;Read error, end program
  204.  
  205. Ems1:      call  GetFromEms       ;Get Turbp Pascal program from EMS memory
  206.  
  207.               ;-- Restore old stack -------------------------------------------
  208.  
  209. CloseUp:   cli                    ;Suppress interrupts
  210.               mov   ss,StackSeg
  211.               mov   sp,StackPtr
  212.               sti                    ;Re-enable interrupts
  213.  
  214.               ;-- Prepare registers for swap ----------------------------------
  215.  
  216.               push  cs                       ;Push DS to CS
  217.               pop   ds
  218.               assume cs:code, ds:code
  219.  
  220.               mov   cx,CoStLen               ;Number of words to be swapped
  221.               mov   di,cx                    ;Move number of words to DI
  222.               dec   di                       ;Decrement by one word
  223.               shl   di,1                     ;Double it
  224.               mov   si,di                    ;move to SI
  225.               add   di,word ptr CostAddr     ;DI+offset addr. of Swap routine
  226.               mov   es,word ptr CostAddr + 2 ;ES gets old CS of Swap routine
  227.               mov   ds,TurboSeg              ;Seg addr. of start of code
  228.  
  229.               ret                            ;Return to SwapOutAndExec
  230.  
  231. StartSwap  endp
  232.  
  233. ;---------------------------------------------------------------------------
  234. ;-- Write2Ems : Write program to be swapped to EMS memory
  235. ;-- Input     : BX = Segment address of EMS page frame
  236. ;--             DS = Codesegment
  237.  
  238. EMS_PLEN   equ 16384                   ;Length of an EMS page
  239.  
  240. HiWLen     dw    ?                     ;Remaining Hi-Word length
  241.  
  242. Write2Ems  proc near
  243.  
  244.               push  ds                    ;Push DS onto stack
  245.               cld                         ;Increment on string instructions
  246.               mov   es,bx                 ;ES points to the page frame
  247.  
  248.               mov   bp,word ptr Len       ;Move Lo-Word length to BP
  249.               mov   ax,word ptr Len + 2   ;Move Hi-Word length to AX
  250.               mov   HiWLen,ax             ;and then to variable
  251.  
  252.               mov   dx,Handle             ;Move EMS Handle to DX
  253.               xor   bx,bx                 ;Start with first logical page
  254.  
  255.               assume cs:code, ds:nothing
  256.  
  257.               jmp short WriECalc          ;Jump in the loop
  258.  
  259. WriELoop:  ;-- Register allocation within this loop -----------------------
  260.               ;
  261.               ;  AX        = Times this, times that
  262.               ;  BX        = Number of logical EMS pages to be addressed
  263.               ;  CX        = Number of bytes to be copied in this execution
  264.               ;  DX        = EMS handle
  265.               ;  ES:DI     = Pointer to first page in EMS page frame (Target)
  266.               ;  DS:SI     = Pointer to first word to be copied      (Start)
  267.               ;  HiWLen:BP = Number of bytes remaining to be copied
  268.  
  269.               mov   ax,4400h              ;Function number for illustration
  270.               int   67h                   ;Call EMM
  271.  
  272.               mov   si,offset CodeEnd     ;Offset for Swapping
  273.               xor   di,di                 ;Write to the start of the EMS page
  274.               mov   ax,cx                 ;Move number to AX
  275.               rep movsb                   ;Copy memory
  276.  
  277.               sub   bp,ax                 ;Remainder of written bytes
  278.               sbb   HiWLen,0              ;Decrement
  279.  
  280.               inc   bx                    ;Increment number of logical page
  281.  
  282.               mov   ax,ds                 ;Starting segment to AX
  283.               add   ax,EMS_PLEN shr 4     ;Increment by written paragraphs
  284.               mov   ds,ax                 ;and move to DS
  285.  
  286. WriECalc:  mov   cx,EMS_PLEN           ;Write EMS_PLEN bytes
  287.               cmp   HiWLen,0              ;More than 64K?
  288.               ja    WriELoop              ;Yes ---> WriELoop
  289.               cmp   bp,cx                 ;No ---> More than EMS_PLEN bytes?
  290.               jae   WriELoop              ;Yes ---> Continue writing
  291.               mov   cx,bp                 ;No ---> Write remainder
  292.               or    cx,cx                 ;No more bytes to write?
  293.               jne   WriELoop              ;No ---> WriELoop
  294.  
  295. WriERet:   pop   ds                    ;Pop DS off of stack
  296.               ret                         ;Return to caller
  297.  
  298. Write2Ems  endp
  299.  
  300. ;---------------------------------------------------------------------------
  301. ;-- GetFromEms : Get the swapped program from EMS memory
  302. ;-- Input   : DS = Code segment
  303.  
  304. GetFromEms proc near
  305.  
  306.               push  ds                    ;Push DS onto the stack
  307.               cld                         ;Increment on string instructions
  308.  
  309.               mov   bp,word ptr Len       ;Move Lo-Word length to BP
  310.               mov   ax,word ptr Len + 2   ;Move Hi-Word length to AX
  311.               mov   HiWLen,ax             ;and from there to variable
  312.  
  313.               mov   dx,Handle             ;Move EMS handle to DX
  314.               xor   bx,bx                 ;Start with first logical page
  315.  
  316.               mov   ds,FrameSeg           ;DS points to the page frame
  317.               push  cs                    ;Set ES to the code segment
  318.               pop   es
  319.  
  320.               assume cs:code, ds:nothing
  321.  
  322.               jmp short GetECalc          ;Jump to the loop
  323.  
  324. GetELoop:  ;-- Register allocation within this loop -----------------------
  325.               ;
  326.               ;  AX        = times this, times that
  327.               ;  BX        = Number of logical EMS pages to be swapped
  328.               ;  CX        = Number of bytes to be copied in this execution
  329.               ;  DX        = EMS handle
  330.               ;  DS:SI     = Pointer to first page in EMS page frame (Start)
  331.               ;  ES:DI     = Pointer to target address in memory
  332.               ;  HiWLen:BP = Number of bytes still to be copied
  333.  
  334.               mov   ax,4400h              ;Function number for illustration
  335.               int   67h                   ;Call EMM
  336.  
  337.               mov   di,offset CodeEnd     ;Offset for Swapping
  338.               xor   si,si                 ;Write to the start of the EMS page
  339.               mov   ax,cx                 ;Move number to AX
  340.               rep movsb                   ;Copy memory
  341.  
  342.               sub   bp,ax                 ;Remainder of written bytes
  343.               sbb   HiWLen,0              ;Decrement
  344.  
  345.               inc   bx                    ;Increment number of logical page
  346.  
  347.               mov   ax,es                 ;Move starting segment to AX
  348.               add   ax,EMS_PLEN shr 4     ;Increment by written paragraphs
  349.               mov   es,ax                 ;and move it to ES
  350.  
  351. GetECalc:  mov   cx,EMS_PLEN           ;Write EMS_PLEN bytes
  352.               cmp   HiWLen,0              ;More than 64K?
  353.               ja    GetELoop              ;Yes ---> GetELoop
  354.               cmp   bp,cx                 ;No ---> More than EMS_PLEN bytes?
  355.               jae   GetELoop              ;Yes ---> Continue writing
  356.               mov   cx,bp                 ;No ---> Write remainder
  357.               or    cx,cx                 ;No more bytes to write?
  358.               jne   GetELoop              ;No ---> GetELoop
  359.  
  360. GetERet:   pop   ds                    ;Pop DS off of stack
  361.               ret                         ;Return to caller
  362.  
  363. GetFromEms endp
  364.  
  365. ;---------------------------------------------------------------------------
  366. ;-- Write2File : Write the program to be swapped to a file
  367. ;-- Returns    : Carry-Flag = 1 : Error
  368.  
  369. Write2File proc near
  370.  
  371. NUM_WRITE  = 2048                      ;Bytes to be written per execution
  372.                                                     ;to power of 2 (max. 2^16)
  373.               assume cs:code, ds:code
  374.  
  375.               push  ds                    ;Push DS onto stack
  376.               mov   bp,4000h              ;Function number for "Write"
  377.               mov   bx,Handle             ;Load file handle
  378.  
  379. WriFStart: mov   di,word ptr Len       ;Move Lo-Word length to DI
  380.               mov   si,word ptr Len + 2   ;Move Hi-Word length to SI
  381.               mov   dx,offset CodeEnd     ;Write offset address
  382.               jmp   short WriFCalc        ;Compute no. of bytes to be written
  383.  
  384. WriFLoop:  ;-- Register allocation within this loop -----------------
  385.               ;
  386.               ;  AX        = times this, times that
  387.               ;  BX        = DOS file handle
  388.               ;  CX        = Number of bytes to be read/written
  389.               ;  DS:DX     = Address at which they should be read/written
  390.               ;  DI:SI     = Number of bytes still to be copied
  391.               ;  BP        = Number of DOS funtion to be called
  392.  
  393.               mov   ax,bp                 ;Load DOS function number
  394.               int   21h                   ;Call DOS interrupt
  395.               jc    WriFEnd               ;Error ---> WriFEnd
  396.               mov   ax,ds                 ;Starting segment to AX
  397.               add   ax,NUM_WRITE shr 4    ;Increment by written paragraphs
  398.               mov   ds,ax                 ;and move to DS
  399.               sub   di,cx                 ;Decrement remainder of
  400.               sbb   si,0                  ;written bytes
  401.  
  402. WriFCalc:  mov   cx,NUM_WRITE          ;Write NUM_WRITE bytes
  403.               cmp   si,0                  ;More than 64K?
  404.               ja    WriFLoop              ;Yes ---> WriFLoop
  405.               cmp   di,cx                 ;No ---> More than NUM_WRITE bytes?
  406.               jae   WriFLoop              ;Yes ---> Continue writing
  407.               mov   cx,di                 ;No ---> Write remainder
  408.               or    cx,cx                 ;No more bytes to write?
  409.               jne   WriFLoop              ;No ---> WriFLoop
  410.  
  411. WriFEnd:   pop   ds                    ;Reload DS
  412. WriFRet:   ret                         ;Return to caller
  413.  
  414. Write2File endp
  415.  
  416. ;---------------------------------------------------------------------------
  417. ;-- GetFromFile : Return the swapped program to memory
  418. ;-- Returns    : Carry-Flag = 1 : Error
  419.  
  420. GetFromFile proc near
  421.  
  422.               assume cs:code, ds:code
  423.  
  424.               push  ds               ;Push DS onto the stack
  425.  
  426.               ;-- Move file pointer to the start of file ----------------
  427.  
  428.               mov   ax,4200h         ;DOS function number
  429.               mov   bx,Handle        ;Load file handle
  430.               xor   cx,cx            ;CX:DX gives its position
  431.               mov   dx,cx
  432.               int   21h              ;Call DOS interrupt
  433.               jc    WriFRet          ;Error ---> WriFRet
  434.  
  435.               ;-- Load file into memory with the help of Write2File -----
  436.  
  437.               mov   bp,3F00h         ;Function number for "Read"
  438.               jmp   WriFStart        ;Jump to Write2File
  439.  
  440. GetFromFile endp
  441.  
  442. ;---------------------------------------------------------------------------
  443. ;-- Terminate : The system can't return to the original Turbo Pascal
  444. ;--             program. The program ends with an error code.
  445.  
  446. Terminate  label near
  447.  
  448.               ;-- Display error message ---------------------------------------
  449.  
  450.               push  cs               ;Set DS to CS
  451.               pop   ds
  452.               mov   dx,offset TerMes ;DS:DX points to the error message
  453.               mov   ah,9             ;Function number for "Display string"
  454.               int   21h              ;Display DOS interrupt
  455.  
  456.               mov   ax,4C01h         ;End program with error code
  457.               int   21h
  458.  
  459.  
  460. ;===========================================================================
  461.  
  462. CodeEnd    equ this byte          ;Copy code from the start of the Turbo
  463.                                              ;Pascal program to this point
  464.  
  465. ;---------------------------------------------------------------------------
  466. ;-- SwapOutAndExec : Swaps the current program to EMS memory or hard disk
  467. ;--                  and starts another program using the DOS EXEC function
  468. ;-- Call from Turbo: SwapOutAndExec( Command,
  469. ;--                                CmdPara : string;
  470. ;--                                ToDisk  : boolean;
  471. ;--                                Handle  : word;
  472. ;--                                Len     : longint );
  473. ;-- Info         : The Command and CmdPara parameters must be configured
  474. ;--                as strings in DOS format.
  475.  
  476. SwapOutAndExec proc near
  477.  
  478. ACommand   equ dword ptr [bp+16]  ;Constants for accessing the
  479. ACmdPara   equ dword ptr [bp+12]  ;specified arguments
  480. AToDisk    equ  byte ptr [bp+10]
  481. AHandle    equ  word ptr [bp+ 8]
  482. ALen       equ dword ptr [bp+ 4]
  483. ARG_LEN    equ 16                 ;Lengths of arguments
  484.  
  485.               assume cs:code, ds:data
  486.  
  487.               push  bp               ;Enable access to the arguments
  488.               mov   bp,sp
  489.  
  490.               ;-- Copy program name to buffer in code segment -----------------
  491.  
  492.               push   ds
  493.               push   ax
  494.               push   dx
  495.               push   cs
  496.               pop    ds
  497.               mov    ah,9
  498.               mov    dx,offset Msg1
  499.               int    21h
  500.               pop    dx
  501.               pop    ax
  502.               pop    ds
  503.  
  504.               mov   dx,ds            ;Mark DS
  505.               push  cs               ;Set ES to CS
  506.               pop   es
  507.  
  508.               lds   si,ACommand      ;DS:SI points to command buffer
  509.               mov   di,offset PrgName ;ES:DI points to PrgName
  510.               cld                    ;Increment on string instructions
  511.               lodsb                  ;Read length of Pascal string
  512.               cmp   al,64            ;More than 64 characters?
  513.               jbe   CmdCopy          ;No ---> CmdCopy
  514.  
  515.               mov   al,64            ;Yes ---> Copy a maximum of 64 characters
  516.  
  517. CmdCopy:   xor   ah,ah            ;Set Hi-Byte to 0 length and
  518.               mov   cx,ax            ;load into the counter
  519.               rep movsb              ;Copy string
  520.  
  521.               ;-- Copy command line in buffer in code segment -----------------
  522.  
  523.               lds   si,ACmdPara      ;DS:SI points to CmdPara buffer
  524.               mov   di,offset CmdBuf ;ES:DI points to CmdBuf
  525.               lodsb                  ;Read length of Pascal string
  526.               cmp   al,126           ;More than 126 characters?
  527.               jbe   ParaCopy         ;No ---> ParaCopy
  528.  
  529.               mov   al,126           ;Yes ---> Copy maximum of 126 characters
  530.  
  531. ParaCopy:  stosb                  ;Store length as first byte
  532.               xor   ah,ah            ;Set Hi-Byte to 0 length and
  533.               mov   cx,ax            ;load into the counter
  534.               rep movsb              ;Copy string
  535.  
  536.               mov   al,0dH           ;Add carriage return
  537.               stosb
  538.  
  539.               ;-- Transfer filename from command line to FCBs -----------------
  540.  
  541.               push  cs               ;Transfer CS to DS
  542.               pop   ds
  543.  
  544.               mov   si,offset CmdBuf+1 ;DS:SI points to CmdBuf + 1
  545.               mov   di,offset FCB1   ;ES:DI points to FCB #1
  546.               mov   ax,2901h         ;Function no.:"Transfer filename to FCB"
  547.               int   21h              ;Call DOS interrupt
  548.  
  549.               mov   di,offset FCB2   ;ES:DI now points to FCB #2
  550.               mov   ax,2901h         ;Function no.: "Transfer filename to FCB"
  551.               int   21h              ;Call DOS interrupt
  552.  
  553.               mov   ds,dx            ;Move old value into DS
  554.  
  555.               ;-- Transfer remaining parameters to variables ------------------
  556.  
  557.               les   ax,ALen          ;Change length
  558.               mov   word ptr Len + 2,es
  559.               mov   word ptr Len,ax
  560.  
  561.               mov   al,AToDisk       ;Change disk flag
  562.               mov   ToDisk,al
  563.  
  564.               mov   ax,AHandle       ;Change handle
  565.               mov   Handle,ax
  566.  
  567.               push  ds               ;Push DS onto the stack
  568.  
  569.               ;-- Exchange variables and program code between labels CodeStart -
  570.               ;-- and CodeEnd with the contents of the PSP code segment
  571.  
  572.               mov   ax,PrefixSeg             ;ES:DI points to start of Turbo
  573.               add   ax,10h                   ;program following PSP
  574.               mov   TurboSeg,ax              ;Mark addr. of Turbo code segment
  575.               mov   es,ax
  576.               xor   di,di
  577.  
  578.               push  cs                       ;Set DS to CS
  579.               pop   ds
  580.               assume cs:code, ds:code
  581.  
  582.               mov   si,offset CodeStart      ;DS:SI points to CodeStart
  583.               and   si,0FFF0h                ;Round off at start of paragraph
  584.  
  585.               mov   cx,CostLen               ;Get number of words to be swapped
  586.               mov   word ptr CoStAddr,si     ;Mark address of
  587.               mov   word ptr CoStAddr + 2,ds ;PARA(Codestart)
  588.  
  589.               mov   dx,es            ;Mark target segment in DX
  590.               cld                    ;Increment on SI/DI string instructions
  591.  
  592.               ;-- Swap loop ---------------------------------------------------
  593.  
  594. dl_loop:   mov   ax,[si]          ;Load word from assembler module
  595.               mov   bx,es:[di]       ;Load word from Turbo Pascal program
  596.               stosw                  ;Write assm. module word to Turbo program
  597.               mov   [si],bx          ;Write Turbo program word to assm. module
  598.               inc   si               ;Set SI to next word
  599.               inc   si               ;(increment SI through STOSW)
  600.               loop  dl_loop          ;Use all words
  601.  
  602.               ;-- Adapt segment address of code segment before calling the ---
  603.               ;-- StartSwap procedure so that variable references to the code
  604.               ;-- segment remain unchanged
  605.  
  606.               mov   ax,offset CodeStart ;Compute number of paragraphs between
  607.               mov   cl,4                ;CodeStart and the start of the
  608.               shr   ax,cl               ;segment, and get segment address in
  609.               sub   dx,ax               ;DX
  610.  
  611.  
  612.               push  cs                  ;Return address to BACK label
  613.               mov   ax,offset back      ;Move onto the stack
  614.               push  ax
  615.  
  616.               push  dx                  ;Push segment address onto stack
  617.               mov   ax,offset StartSwap ;Move offset address onto stack
  618.               push  ax
  619.  
  620.               retf                      ;FAR-RET to StartSwap
  621.  
  622. Msg2       db 13,10,13,10
  623.               db "╔════════════════════════════╗",13,10
  624.               db "║ Done_Swap: Swapping in     ║",13,10
  625.               db "╚════════════════════════════╝"
  626.               db 13,10,13,10,"$"
  627.  
  628. back:      ;----------------------------------------------------------------
  629.               ;-- Returns original program to main memory and executes the
  630.               ;-- program.
  631.               ;-- Registers have the following contents:
  632.               ;--   DS:SI = End of assembler code following the PSP
  633.               ;--   ES:DI = End of Turbo code in the SWAP unit
  634.               ;--   CX    = Number of words
  635.               ;----------------------------------------------------------------
  636.  
  637.               assume cs:code, ds:nothing
  638.  
  639.               std                    ;Decrement string instructions by SI/DI
  640.  
  641.               ;-- Swap back loop ----------------------------------------------
  642.  
  643.               push   ds
  644.               push   ax
  645.               push   dx
  646.               push   cs
  647.               pop    ds
  648.               mov    ah,9
  649.               mov    dx,offset Msg2
  650.               int    21h
  651.               pop    dx
  652.               pop    ax
  653.               pop    ds
  654.  
  655. ul_loop:   mov   bx,es:[di]       ;Get byte from old memory range
  656.               mov   ax,[si]          ;Get byte from current memory range
  657.               mov   [si],bx          ;Byte from old memory rng to current rng
  658.               dec   si               ;Set SI to previous word
  659.               dec   si
  660.               stosw                  ;Byte from current memory rng to old rng
  661.               loop  ul_loop          ;Repeat until memory ranges are exchanged
  662.  
  663.               pop   ds               ;Pop DS off of stack
  664.               assume ds:data
  665.  
  666.               pop   bp               ;Pop BP
  667.  
  668.               ;-- MOV SP,BP must not be given, since SP doesn't change
  669.  
  670.               xor   ah,ah            ;Place error code in AX
  671.               mov   al,Error_Code
  672.  
  673.               ret ARG_LEN            ;Return to caller, clear arguments
  674.                                              ;from stack
  675.  
  676. SwapOutAndExec endp
  677.  
  678.  
  679. ;---------------------------------------------------------------------------
  680. ;-- InitSwapa : Computes the number of bytes/words allocated for a program
  681. ;--             swap with the start of the Turbo program in memory
  682. ;-- Input        : none
  683. ;-- Output       : number of bytes
  684. ;-- Pascal call  : function InitSWapa : word;
  685. ;-- Info         : This procedure must be called before the
  686. ;--                first call to SwapOutAndExec!
  687.  
  688. InitSwapa  proc near
  689.  
  690.               assume cs:code, ds:data
  691.  
  692.               mov   bx,offset CodeStart      ;AX points to start of code
  693.               and   bx,0FFF0h                ;Round off at start of paragraph
  694.               mov   ax,offset CodeEnd        ;BX points to end of code
  695.               sub   ax,bx                    ;Compute number of bytes
  696.               inc   ax                       ;Convert CX to words
  697.               shr   ax,1
  698.               mov   CoStLen,ax               ;Mark number of words to be swapped
  699.               shl   ax,1                     ;Convert to bytes
  700.  
  701.               ;-- Return contents of AX as function result
  702.  
  703.               ret                            ;Return to caller
  704.  
  705. InitSwapa  endp
  706.  
  707. ;---------------------------------------------------------------------------
  708.  
  709. CODE       ends                   ;End of code segment
  710.               end                    ;End of program
  711.