[Back to DOS SWAG index] [Back to Main SWAG index] [Original]
{
EH> I was wondering if there was some way that I could convert a Pascal
EH> exe to some sys file that the computer loads/runs when booting.
You can use this, the only problem is that the units are not initialized (the
optional code before the last end. in a unit is not executed), and so system
(WriteLn/ReadLn) and crt (WriteLn/ReadLn) don't work.
===
{ DEVCLINE.PAS: Example of a device driver in TP, Arne de Bruijn, 19960302. }
{ Released to the Public Domain. }
{ This example shows the 'commandline' of the device driver }
{ (everything after DEVICE=), and removes itself from memory. }
type
TReqHead=record { Structure passed to us by DOS }
ReqLen:byte;
SubUnit:byte;
Cmd:byte;
Status:word;
Reserved:array[0..7] of byte;
MediaDesc:byte;
Address:pointer;
case byte of
0:(DevLine:pointer; DriveName:byte);
255:
(Count:word; Sector:word);
end;
var
DevStack:array[0..4094] of byte; { Own stack, DOS's isn't that big }
EndOfStack:byte;
ReqHead:^TReqHead;
procedure DevStrat; far; forward;
procedure DevIntr; far; forward;
procedure Header; assembler;
{ The trick: put the device header as the very first procedure your source, }
{ so TP places it at the start of the .exe }
asm
dd -1 { Next device in chain (updated by MS-DOS) }
dw 0 { Device attribute, now block device }
dw offset DevStrat { Offset of strategy routine }
dw offset DevIntr { Offset of interrupt routine }
db 0,0,0,0,0,0,0,0 { For block: 1 byte no of subunits, 7 bytes reserved }
end;
procedure DevStrat; assembler;
{ Strategy routine, save ES:BX for later use }
asm
push ax
push ds
mov ax,seg @Data
mov ds,ax
mov word ptr [ReqHead],bx
mov word ptr [ReqHead+2],es
pop ds
pop ax
end;
procedure WriteStr(S:string); assembler;
{ Units not initalized, can't use some System procs (WriteLn, etc.) }
asm
cld
mov bx,ds
lds si,S
lodsb
mov cl,al
xor ch,ch
jcxz @NoStr
@PrtStr:
lodsb
mov ah,2
mov dl,al
int 21h
loop @PrtStr
@NoStr:
mov ds,bx
end;
procedure TPIntr;
{ Called by asm proc, ReqHead contains pointer to request header, }
{ Local stack in datasegment used (now 4k) }
type
AByte=array[0..65534] of byte;
var
S:string[50];
I,IntNo:byte;
begin
if ReqHead^.Cmd=0 then { Initialization? }
begin
S[0]:=#50; { Max len of string }
Move(ReqHead^.DevLine^,S[1],50);{ Copy from DOS buffer }
I:=pos(#10,S); { Search for #10 }
if I>0 then { Found? }
begin
byte(S[0]):=I-1; { That's the len for now }
I:=pos(#13,S); { Also a #13? }
if I>0 then byte(S[0]):=I-1; { That must be the length }
end;
WriteStr('Cmdline:"'+S+'"'#13#10); { Display 'command line' }
{ Remove device driver from memory }
ReqHead^.MediaDesc:=0; { Number of components }
ReqHead^.Address:=ptr(cseg,0); { First free address }
ReqHead^.Status:=$100; { Status OK }
end
else
ReqHead^.Status:=$9003; { Status unknown cmd }
end;
procedure DevIntr; assembler;
asm
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
mov ax,seg @Data
mov ds,ax
mov bx,ss
mov cx,sp
mov ss,ax { Set up local stack }
mov sp,offset EndOfStack+1
push bx
push cx
call TPIntr
pop cx { Restore old stack pointer }
pop bx
mov ss,bx
mov sp,cx
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
end;
begin
ReqHead:=@Header; {To include it in linking (smartlinker skips it otherwise)}
{ This is executed when run from the commandline }
WriteStr('Must be loaded from CONFIG.SYS with DEVICE=DEVCLINE.EXE'#13#10);
end.
[Back to DOS SWAG index] [Back to Main SWAG index] [Original]