;------------------------------------------------------------------------- ; Exec function with swapping to disk. (c) 1990,1991 Philippe Leybaert ;------------------------------------------------------------------------- % MODEL MEM_MOD LOCALS @@ PUBLIC _swapshell EXTRN __psp : WORD EXTRN _shell_windowed : WORD EXTRN _shell_updateline: WORD EXTRN _shell_swap : WORD EXTRN _shell_swapname : PTR EXTRN _use_ems : BYTE EXTRN _tsw_vsize : WORD EXTRN _tsw_hsize : WORD EXTRN _tsw_videobase : FAR PTR CODESEG _TEXT numpara dw (?) ; number of paragraphs reserved by compiler savedpara dw (?) ; number of paragraphs to keep swapsize dw (?) ; size of swapfile (# paragraphs) swapseg dw (?) ; segment of start of swapregion main_ss dw (?) ; saved for swapshell main_sp dw (?) ; function (compiler stack saved here) old_ss dw (?) ; saved for old_sp dw (?) ; exec function saved_psp dw (?) ; psp of my program retval dw (?) ; return value of process swapmode dw (?) ; swap code/data? ems_handle dw (?) ; EMS swapspace handle num_cols dw (?) ; # screen columns num_lines dw (?) ; # screen lines use_ems db (?) ; Use EMS? data_seg dw (?) prgname db 128 DUP (0) swapname db 13 DUP (0) old_dir db '\' db 69 DUP (0) old_disk dw 0 displayline dw 132 dup (?) EVEN cur_x dw 0 cur_y dw 0 LABEL old21 DWORD old21_off dw 0 old21_seg dw 0 LABEL old1c DWORD old1c_off dw 0 old1c_seg dw 0 LABEL videoptr DWORD video_off dw 0 video_seg dw 0 dw 99 DUP (?) ; new stack (100 words) newstackptr dw 0 parablock dw 0 dw offset comlen dw @Code dd 0FFFFFFFFh dd 0FFFFFFFFh comlen db 0 comline db 127 dup (0) PROC exec NEAR push bx push cx push dx push di push si push bp push ds push es mov [cs:old_ss],ss ; save stack mov [cs:old_sp],sp ; (exec function destroys ss an sp) push cs ; es <- cs pop es mov dx,offset prgname ; get program name mov bx,offset parablock ; get parameter block mov ax,4B00h ; int 21h ; call DOS EXEC function cli mov ss,[cs:old_ss] ; restore stack pointer mov sp,[cs:old_sp] sti mov ah,4Dh int 21h xor ah,ah mov [cs:retval],ax pop es pop ds pop bp pop si pop di pop dx pop cx pop bx ret ENDP exec PROC shrink_exec NEAR ; ES: segment , BX: # para's to allocate assume ds:@Code cmp [swapmode],0 je @@noshrink mov ax,4a00h ; shrink memory size to minimum int 21h ; (only this module remains) @@noshrink: call near exec ; shell mov ah,0Eh ; mov dl,[byte old_disk] ; Restore current disk int 21h ; mov ah,3Bh ; mov dx,offset old_dir ; Restore current directory int 21h ; cmp [swapmode],0 je @@noexpand mov ax,[saved_psp] mov es,ax mov bx,[numpara] mov ax,4A00h int 21h ; give back memory we stole push ds ; save data segment mov cx,[swapsize] mov ax,[swapseg] mov ds,ax call read_para pop ds ; restore data segment @@noexpand: ret ENDP shrink_exec PROC read_para NEAR ; read cx paragraphs to ds:0 push ds push ax push bx push cx push dx push si push di push es cmp [cs:use_ems],0 je @@use_file mov ah,40h int 67h or ah,ah jnz @@use_file mov dx,[cs:ems_handle] mov ah,41h int 67h push ds pop es mov ds,bx ; es = page frame xor bx,bx ; bx = logical page index @@ems_loop: cmp cx,0400h jb @@ems_remainder push cx mov ax,4400h int 67h ; map page bx to phys.page 0 mov cx,02000h cld xor si,si xor di,di rep movsw ; transfer data to page frame inc bx pop cx sub cx,0400h mov ax,es add ax,0400h mov es,ax jmp short @@ems_loop @@ems_remainder: mov ax,4400h int 67h ; map page bx to phys.page 0 shl cx,1 ; Convert # paragraphs -> #words shl cx,1 shl cx,1 cld xor si,si xor di,di rep movsw ; transfer data to page frame mov ah,45h int 67h ; Free EMS jmp short @@quit @@use_file: push ds mov ax,cs mov ds,ax assume ds:@Code mov ax,3D00h mov dx,offset swapname int 21h ; open swap-file mov bx,ax pop ds @@loopke: cmp cx,0F00h jb @@remainder push cx mov cx,0F000h xor dx,dx mov ax,3F00h int 21h pop cx sub cx,0F00h mov ax,ds add ax,0F00h mov ds,ax jmp short @@loopke @@remainder: shl cx,1 shl cx,1 shl cx,1 shl cx,1 xor dx,dx mov ax,3F00h int 21h mov ax,3E00h int 21h ; close file mov ax,cs mov ds,ax mov dx,offset swapname mov ax,4100h int 21h @@quit: pop es pop di pop si pop dx pop cx pop bx pop ax pop ds ret ENDP read_para PROC disp NEAR push cx push si push di push bp cmp al,0ah jne no_lf mov cx,[cs:num_lines] dec cx inc [cs:cur_y] cmp [cs:cur_y],cx ; At bottom of screen? jne upd_cursor dec [cs:cur_y] ; Yep, scroll up jmp short scroll_up no_lf: cmp al,0dh jne no_cr mov [cs:cur_x],0 jmp short upd_cursor no_cr: cmp al,8 jne no_bs cmp [cs:cur_x],0 je @@ok dec [cs:cur_x] jmp short upd_cursor no_bs: mov ah,0eh xor bx,bx int 10h mov cx,[cs:num_cols] inc [cs:cur_x] cmp [cs:cur_x],cx ; At right of window? jne @@ok mov [cs:cur_x],0 ; Yep, linefeed inc [cs:cur_y] mov cx,[cs:num_lines] dec cx cmp [cs:cur_y],cx ; At bottom of screen jne upd_cursor dec [cs:cur_y] scroll_up: mov ax,0601h mov cx,0000h mov dl,4Fh mov dh,[byte cs:num_lines] dec dh dec dh mov bh,7 int 10h upd_cursor: mov ah,2 mov bh,0 mov dh,[byte cs:cur_y] mov dl,[byte cs:cur_x] int 10h @@ok: pop bp pop di pop si pop cx ret ENDP disp PROC new21 cmp ah,2 je catch cmp ah,6 jne test_9 cmp dl,0ffh jne catch test_9: cmp ah,9 je catch cmp ah,40h jne nocatch cmp bx,1 je catch cmp bx,2 je catch nocatch: jmp [cs:old21] catch: push ax push bx push cx push dx push si push di push bp push ds push es cmp ah,2 jne no_2 mov al,dl call disp jmp short done_catch no_2: cmp ah,6 jne no_6 mov al,dl call disp jmp short done_catch no_6: cmp ah,9 jne no_9 mov si,dx @@l: mov al,[ds:si] cmp al,'$' je done_catch call disp inc si jmp short @@l no_9: mov si,dx @@l2: or cx,cx jz ret_40 mov al,[ds:si] call disp inc si dec cx jmp short @@l2 ret_40: pop es pop ds pop bp pop di pop si pop dx pop cx pop bx pop ax mov ax,cx clc iret done_catch: pop es pop ds pop bp pop di pop si pop dx pop cx pop bx pop ax iret ENDP new21 timer_val dw 0 PROC new1c push ax inc [cs:timer_val] mov ax,[cs:timer_val] and ax,7 jnz @@nodisp push cx push si push di push bp push ds push es push cs pop ds assume ds:@Code les di,[videoptr] mov si,offset displayline cld mov cx,80 rep movsw pop es pop ds pop bp pop di pop si pop cx @@nodisp: pop ax jmp [cs:old1c] ENDP new1c startswap: ; all data/code past this point can be ; swapped (who cares!) PROC _swapshell ARG command:PTR push bp mov bp,sp push ds push si push di mov ax,ds mov [cs:data_seg],ax mov ax,[_tsw_vsize] mov [cs:num_lines],ax mov ax,[_tsw_hsize] mov [cs:num_cols],ax mov ax,[_shell_swap] mov [cs:swapmode],ax mov al,[_use_ems] mov [cs:use_ems],al call near install_isr mov ax,[__psp] ; store psp for future use mov [cs:saved_psp],ax mov si,offset _shell_swapname push cs pop es mov di,offset swapname mov cx,13 cld rep movsb lds si,[command] mov di,offset prgname @@lp: mov al,[si] cmp al,' ' je @@qt or al,al je @@qt mov [cs:di],al inc si inc di jmp short @@lp @@qt: mov [byte cs:di],0 mov al,[si] inc si cmp al,' ' je @@qt dec si mov cx,0 mov di,offset comline @@lp2: mov al,[si] or al,al je @@qt2 mov [cs:di],al inc si inc di inc cx jmp short @@lp2 @@qt2: mov [byte cs:di],13 mov di,offset comlen mov [cs:di],cl mov ax,@Code ; ds = code segment mov ds,ax assume ds:@Code ; tell Tasm where ds points to mov [main_ss],ss ; save compiler stack mov [main_sp],sp mov ax,cs cli mov ss,ax ; set my own stack mov sp,offset newstackptr sti mov ax,[saved_psp] ; get psp address dec ax ; get address of MCB mov es,ax mov ax,[es:3] ; get number of paragraphs reserved mov [numpara],ax ; and store it mov bx,offset startswap ; we can swap from this point mov cl,4 shr bx,cl ; convert to # paragraphs add bx,@Code mov ax,[saved_psp] ; how many paragraphs sub bx,ax ; must remain? add bx,2 ; 2 extra paragraphs (safe!) mov es,ax ; es <- psp mov [savedpara],bx ; store it push bx ; push number of paragraphs push es ; push psp address mov cx,[numpara] ; get number of paragraphs reserved sub cx,bx ; calculate # paragraphs to save mov [swapsize],cx ; store for later use mov ax,es ; get psp add ax,bx ; calculate address for swap-start mov [swapseg],ax ; store for later use push ds ; save data segment cmp [swapmode],0 je @@nowrite mov ds,ax ; set ds to region to save call near write_para ; save file @@nowrite: pop ds mov ah,19h ; int 21h ; Save current disk mov [byte old_disk],al ; mov si,offset old_dir+1 ; mov dl,0 ; Save current directory mov ah,47h ; int 21h ; pop es pop bx call near shrink_exec cli mov ss,[main_ss] ; restore compiler stack mov sp,[main_sp] sti call near remove_isr pop di pop si pop ds pop bp mov ax,[cs:retval] ; set return value ret ENDP _swapshell PROC write_para NEAR ; write cx paragraphs from ds:0 push ds push ax push bx push cx push dx push si push di push es cmp [cs:use_ems],0 je @@use_file mov ah,40h int 67h or ah,ah jnz @@use_file push cx mov bx,cx mov cl,10 shr bx,cl inc bx pop cx mov ah,43h int 67h or ah,ah jnz @@use_file mov [cs:ems_handle],dx mov ah,41h int 67h mov es,bx ; es = page frame xor bx,bx ; bx = logical page index @@ems_loop: cmp cx,0400h jb @@ems_remainder push cx mov ax,4400h int 67h ; map page bx to phys.page 0 mov cx,02000h cld xor si,si xor di,di rep movsw ; transfer data to page frame inc bx pop cx sub cx,0400h mov ax,ds add ax,0400h mov ds,ax jmp short @@ems_loop @@ems_remainder: mov ax,4400h int 67h ; map page bx to phys.page 0 shl cx,1 ; Convert # paragraphs -> #words shl cx,1 shl cx,1 cld xor si,si xor di,di rep movsw ; transfer data to page frame jmp short @@quit @@use_file: mov [cs:use_ems],0 push ds push cx push cs pop ds mov dx,offset swapname mov ax,3c00h ; Create xor cx,cx ; swap-file int 21h pop cx pop ds mov bx,ax @@loopke: cmp cx,0F00h jb @@remainder push cx mov cx,0F000h xor dx,dx mov ax,4000h int 21h pop cx sub cx,0F00h mov ax,ds add ax,0F00h mov ds,ax jmp short @@loopke @@remainder: shl cx,1 shl cx,1 shl cx,1 shl cx,1 xor dx,dx mov ax,4000h int 21h mov ax,3E00h int 21h @@quit: pop es pop di pop si pop dx pop cx pop bx pop ax pop ds ret ENDP write_para PROC install_isr NEAR push ax push bx push cx push dx push ds push es push si push di push bp mov ax,[cs:data_seg] mov ds,ax cmp [_shell_windowed],0 je @@nowindow mov ax,3521h int 21h mov ax,es mov [cs:old21_seg],ax mov [cs:old21_off],bx mov ax,2521h mov dx,offset new21 push ds push cs pop ds int 21h pop ds mov [cs:cur_x],0 mov [cs:cur_y],0 mov ax,0600h mov cx,0 mov dl,4Fh mov dh,[byte cs:num_lines] dec dh dec dh mov bh,7 int 10h mov dx,0 mov bh,0 mov ah,2 int 10h @@nowindow: cmp [_shell_updateline],0 je @@notupdated mov ax,351Ch int 21h mov ax,es mov [cs:old1c_seg],ax mov [cs:old1c_off],bx mov ax,251Ch mov dx,offset new1c push ds push cs pop ds int 21h pop ds push ds mov ax,[_shell_updateline] dec ax mov cx,[cs:num_cols] shl cx,1 mul cx lds si,[_tsw_videobase] add si,ax mov ax,ds mov [cs:video_seg],ax mov [cs:video_off],si mov ax,[cs:num_lines] dec ax mov cx,[cs:num_cols] shl cx,1 mul cx mov si,ax ; SI = (num_lines-1) * num_cols * 2 push cs pop es mov di,offset displayline mov cx,[cs:num_cols] cld rep movsw pop ds @@notupdated: cmp [_shell_windowed],0 jne @@done mov ax,0600h mov cx,0 mov dl,[byte cs:num_cols] dec dl mov dh,[byte cs:num_lines] dec dh mov bh,7 int 10h mov dx,0 mov bh,0 mov ah,2 int 10h @@done: pop bp pop di pop si pop es pop ds pop dx pop cx pop bx pop ax ret ENDP install_isr PROC remove_isr NEAR push ds mov ax,[cs:data_seg] mov ds,ax cmp [_shell_windowed],0 je @@nowindowrestore push ds mov ax,2521h lds dx,[cs:old21] int 21h pop ds @@nowindowrestore: cmp [_shell_updateline],0 je @@noupdaterestore mov ax,251Ch lds dx,[cs:old1c] int 21h @@noupdaterestore: pop ds ret ENDP remove_isr ENDS END