Contributor: ARNE DE BRUIJN { 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.