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.


AltStyle によって変換されたページ (->オリジナル) /