[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]