; ; GRDB ; ; Copyright(c) LADsoft ; ; David Lindauer, gclind01@starbase.spd.louisville.edu ; ; LOADER.ASM ; ; Function : COM/EXE file loader ; .model small .386 public MakeEmptyProg, userbasepsp, filelen,loadfile,loadcommand,exeflag public ParseProgName,exestats,LoadProgram public lastcs,lastip,lastexe include env.ase include mtrap.ase include dump.ase include dos.ase include memory.ase include prints.ase include input.ase headstruct struc sig dw ? ; EXE signature- we exit if not 'MZ' mlength dw ? ; length modulo 512 pages dw ? ; length in pages, rounded UP relocs dw ? ; Number of relocation items headsize dw ? ; Size of header in paragraphs ; We will later assume this is less than 1000h ; paragraphs but you probably should fix that minalloc dw ? ; Minimum memory needed maxalloc dw ? ; Maximum memory desired dispss dw ? ; starting stack basesp dw ? ; checksum dw ? ; We'll ignore the checksum. Dos ignores it too ; if it is zero baseip dw ? ; Starting CS:IP dispcs dw ? relocofs dw ? ; Offset to relocation table overlay dw ? ; I never saw a program with the overlay field set ; so I don't know what happens here... headstruct ends .data loadfile db 80 DUP (?) loadcommand db 128 DUP (?) filelen dd 0 handle dw 0 exeflag db 0 header headstruct ? userbasepsp dw 0 relox dd ? lastexe db 0 lastip dd 0 lastcs dw 0 .code ; ; clear FCBs in PSP ; InitFCB PROC push es mov es,[userbasepsp] sub al,al stosb mov cx,11 mov al,20h rep stosb pop es ret InitFCB ENDP ; ; create an empty program area ; MakeEmptyProg PROC mov [filelen],0 mov [exeflag],0 push si ; refresh env call CopyEnv pop si jc nomem mov bx,-1 ; minimum emem needed mov ah,48h int 21h cmp al,8 jnz nomem cmp bx,200h jc nomem push bx ; space for their PSP mov ah,48h int 21h mov [userbasepsp],ax mov [userpsp],ax mov dx,ax ; create it mov ah,55h int 21h mov fs,[psp] mov ax,fs:[2] mov fs,[userbasepsp] mov fs:[2],ax call SetDebugPSP ; put us back at ours now pop ax cmp ax,1000h ;initial SP mov bx,0ffeeh jnc meok movzx ebx,ax shl bx,4 sub bx,18 meok: mov [dreip],0 ; init all regs to defaults mov [dreax],0 mov [drebx],0 mov [drecx],0 mov [dredx],0 mov [dresp],ebx mov [drebp],0 mov [dresi],0 mov [dredi],0 mov ax,[userbasepsp] mov [drcs],ax mov [drds],ax mov [dres],ax mov [drfs],ax mov [drgs],ax mov [drss],ax mov [indexseg],ax mov [dreip],100h mov [index],100h mov word ptr [reflags],202h ; flags mov word ptr fs:[bx],0 mov fs,[userbasepsp] ; set up env seg mov bx,[envseg] mov fs:[2ch],bx mov ax,[userbasepsp] ; tag the arena entries mov bx,ax dec bx call tagarena mov ax,[userbasepsp] mov bx,[envseg] dec bx call tagarena mov di,5ch ; set up FCBs call InitFCB mov di,6ch call InitFCB clc nomem: ret MakeEmptyProg ENDP ; ; throw a file name into an FCB, just for the old days :) ; tofcb PROC call WadeSpace sub al,al cmp byte ptr [si+1],':' jnz nodrive lodsw sub al,'a'-1 nodrive: stosb push si fxlp: lodsb cmp al,':' jz tfcberr cmp al,'\' jz tfcberr cmp al,'/' jz tfcberr cmp al,',' jz fxdn cmp al,' ' jz fxdn or al,al jz fxdn jnz fxlp fxdn: xchg [esp],si mov cx,8 mvlp: lodsb cmp al,'.' jz dodot cmp si,[esp] jnc tfcbx and al,0dfh stosb loop mvlp wade1: lodsb cmp al,'.' jz dodot cmp si,[esp] jnc tfcbx jmp wade1 dodot: mov cl,3 sub di,5 and di,0fff8h add di,13 ddl: lodsb cmp si,[esp] jnc tfcbx and al,0dfh stosb loop ddl tfcbx: pop si test byte ptr [si],0ffh jz tfcberr clc ret tfcberr: stc ret tofcb ENDP ; ; put a command line in user psp ; SetUserCommand PROC push es mov es,[userbasepsp] mov al,1 mov cx,80h mov di,80h rep stosb mov di,81h mov si,offset dgroup:loadcommand mov byte ptr es:[80h],0 mov cx,126 cml_lp: lodsb or al,al jz cml_dn stosb inc byte ptr es:[80h] loop cml_lp cml_dn: mov al,0dh stosb mov si,offset dgroup:loadcommand mov di,05ch call tofcb jc comdone mov di,06ch call tofcb comdone: pop es ret SetUserCommand ENDP ; ; parse the program name/command line as set in a W/L command ; ParseProgName PROC lodsb cmp al,' ' jz ParseProgName dec si mov es:[loadfile],0 mov es:[loadcommand],0 mov di,offset dgroup:loadfile ppnlp: lodsb cmp al,' ' jz ppngot cmp al,13 jz ppcgot or al,al jz ppngot stosb jmp ppnlp ppngot: mov al,0 stosb dec si mov di,offset dgroup:loadcommand ppclp: lodsb cmp al,13 jz ppcgot or al,al jz ppcgot stosb jmp ppclp ppcgot: dec si mov al,0 stosb push ds push es pop ds push si mov si,offset dgroup:loadfile call QualifyName pop si pop ds ret ParseProgName ENDP ; ; main program loader ; LoadProgram PROC mov [lastexe],0 ; assume com push ax ; unload prog call UnLoadProgram pop ax or ax,ax jnz lcm call LoadExe ; EXE load jmp lpfin lcm: call LoadCom ; COM load lpfin: jc lpnomod mov word ptr [drecx],ax ; set stats mov word ptr [drecx+2],0 shr eax,16 mov [drebx],eax call SetUserCommand mov si,offset dgroup:loadfile ; tag arean with prog name mov ax,[userbasepsp] mov bx,ax dec bx call tagarena mov ax,[userbasepsp] mov bx,[envseg] dec bx call tagarena call SetEnvName clc lpnomod: ret LoadProgram ENDP ; ; com file load, just grab the data ; LoadCom PROC mov ax,3d00h ; Open the file mov dx,offset dgroup:loadfile int 21h mov bx,ax jc failure LoadCom2: mov ax,4200h sub cx,cx sub dx,dx int 21h jc failure mov si,[userbasepsp] push ds add si,10h rdlp: mov ds,si mov ax,3f00h ; Read the file mov cx,8000h sub dx,dx int 21h jc failure2 add si,800H movzx eax,ax add es:[filelen],eax cmp ax,8000H jz rdlp clc failure2: pop ds failure: pushf mov ax,3e00h ; close the file int 21h popf jnc loadok mov [filelen],0 mov [exeflag],0 loadok: mov eax,[filelen] ret LoadCom ENDP ; ; exe file load ; LoadEXE PROC mov si,offset dgroup:loadfile ls_lp1: lodsb or al,al jz LoadCom cmp al,'.' jnz ls_lp1 mov eax,[si] and eax,0ffffffh cmp eax,"exe" jnz LoadCom ; ; Open the file ; mov ax,3d00h ; Open the file mov dx,offset dgroup:loadfile int 21h mov bx,ax mov [handle],ax jc failure ; ; Read the basic part of the header ; mov ax,3f00h ; Read the file mov dx,offset dgroup:header mov cx,1ch int 21h jc failure mov ax,[header.sig] ; Fail if not an EXE cmp ax,"ZM" jnz LoadCom2 mov [exeflag],1 ; ; Load exe file movzx ecx,[header.pages] ; calculate size of prog dec cx shl ecx,9 movzx eax,[header.mlength] add ecx,eax movzx eax,[header.headsize] shl eax,4 sub ecx,eax jc failure mov [filelen],ecx mov ax,[userbasepsp] mov fs,ax add ax,[header.minalloc] add ax,10h cmp fs:[2],ax jc failure mov ax,fs dec ax mov fs,ax mov ax,fs:[3] cmp ax,[header.maxalloc] jbe nomemresize mov bx,[header.maxalloc] push es mov es,[userbasepsp] mov ah,4ah int 21h pop es nomemresize: mov si,[userbasepsp] add si,10h mov dx,[header.headsize] shl dx,4 push ecx ; point at program data sub cx,cx mov ax,4200h mov bx,cs:[handle] int 21h pop ecx jc failure push ds redlp: push ecx mov ds,si mov ax,3f00h ; Read the file mov cx,8000h sub dx,dx int 21h jc failure2 pop ecx add si,800h sub ecx,8000h jnc redlp pop ds test cs:[header.relocs],-1 ; get out if no relocs jz lfexit mov si,[userbasepsp] add si,10h sub cx,cx mov dx,cs:[header.relocofs] ; position to start of reloc table mov ax,4200h int 21h jc failure mov cx,[header.relocs] ; Get number of relocs mov bx,[handle] relolp: push cx ; Load a reloc mov cx,4 mov dx, offset dgroup:relox mov ah,3fh int 21h pop cx jc failure add word ptr [relox+2],si ; Adjust to phys address lfs di,[relox] ; Readjust the reloc add fs:[di],si loop relolp ; continue till done lfexit: mov ax,[userbasepsp] add ax,10h add [header.dispcs],ax add [header.dispss],ax movzx eax,[header.baseip] mov [dreip],eax movzx eax,[header.basesp] mov [dresp],eax mov ax,[header.dispcs] mov [drcs],ax mov ax,[header.dispss] mov [drss],ax mov ah,3eh int 21h mov [lastexe],1 mov eax,[dreip] mov [lastip],eax mov ax,[drcs] mov [lastcs],ax mov eax,[filelen] movzx ebx,[header.headsize] shl ebx,4 add eax,ebx sub eax,512 clc ret LoadEXE ENDP ; ; used by status screen to display EXE status ; ExeStats PROC test [filelen],-1 jz noexe Msg <13,10,"File length: "> mov eax,[filelen] call PrintDWord test [exeflag],0ffh jz noexe mov cx,[userbasepsp] add cx,10h Msg <13,10,"CS:IP = "> mov ax,[header.dispcs] call printword mov dl,':' call PutChar mov ax,[header.baseip] call printword Msg <13,10,"SS:SP = "> mov ax,[header.dispss] call printword mov dl,':' call PutChar mov ax,[header.basesp] call printword Msg <13,10,"minalloc: "> mov ax,[header.minalloc] call printword Msg <" maxalloc: "> mov ax,[header.maxalloc] call printword Msg <13,10,"relocs: "> mov ax,[header.relocs] call printword noexe: ret ExeStats ENDP end