[Back to HARDWARE SWAG index] [Back to Main SWAG index] [Original]
{... so there I was, sitting in a bar when a known C Programmer }
{comes up to me and sniggers "still doing it in Pascal eh?" }
{"Yup" I replied, and tossed the bartender another hundred. }
{"Yeah well, when you're ready For a Real language, only C has }
{all the aces." }
{I'm a Pascal Programmer. I don't have to take that. "Such as?"}
{I hoped he'd bite and he did. }
{"Such as disk sector reading and writing For starters." }
{"Well I hope you're not bluffin', 'cause here's a trick that }
{I'll bet you ain't covered." }
{I pulled it out With a swish and laid it on the table. "Even }
{provides support For >32M volumes, which the C run-time library }
{manual Forgets to tell you it won't do." }
{"Huh? Where?" }
{"Right here" I said. "Just where it says... }
Program AbsReadTest;
{This Program demonstrates a C-style absread and absWrite For TP.}
{As is, it reads the boot sector off drive A:, and optionally }
{Writes it out to the very last sector on drive A: (assumes 1.2Meg}
{This Program IS dangerous, and is released to the public domain.}
{I take no responsibility For use or misuse, deliberate or }
{accidental, of this Program or any Program which Uses the }
{techniques described herein. }
{Author: Mitch Davis 3:634/384.6 +61-3-890-2062 v1.0 28-Jun-92. }
Var bp:Pointer; {Will point to the buffer For the sector data}
Function absread (drive:Char; nsects:Word; lsect:Word; buffer:Pointer):Boolean;
{Works just like the C runtime one- including being restricted to 32M volumes!}
{drive is a Character, nsects is the number of sectors, and lsect is the first}
{sector. buffer points to the buffer you'd like filled from disk. Function }
{returns True if there was an error, or False if all went well. }
Var kludgebuff:Array [0..$1f] of Byte; {Read Ralf Brown's interrupt listing}
kludgePtr:Pointer; {Int 25h - ES:[BP+1E] may change }
begin
kludgePtr := @kludgebuff;
absread := True;
if drive < 'A' then Exit;
if drive > 'Z' then Exit;
Asm
push es
push bp
push di
les di, kludgePtr
mov al, drive { Gets the passed parameter. }
and al, 1fh { Cvt from ASCII to drive num }
dec al { Adjust because A: is drive 0 }
mov cx, nsects { number of sectors to read }
mov dx, lsect { starting at sector.. }
push ds
lds bx, buffer { Get the address of the buffer }
mov bp, di
push si
int 25h { Do the drive read. }
pop si { Remove the flags int 25h leaves on stack}
pop si
pop ds
pop di
pop bp
pop es
jc @1
mov ah, 0 { No errors, so set Function to False }
@1:
mov @result, ah
end;
end;
Function absWrite
(drive:Char; nsects:Word; lsect:Word; buffer:Pointer):Boolean;
{Works just like the C one - including being restricted to 32M volumes!}
{drive is a Character, nsects is the number of sectors, and lsect is the first}
{sector. buffer points to the buffer you'd like filled from disk. Function }
{returns True if there was an error, or False if all went well. }
Var kludgebuff:Array [0..$1f] of Byte;
kludgePtr:Pointer;
begin
kludgePtr := @kludgebuff;
absWrite := True;
if drive < 'A' then Exit;
if drive > 'Z' then Exit;
Asm
push es
push bp
push di
les di, kludgePtr
mov al, drive { Gets the passed parameter. }
and al, 1fh { Cvt from ASCII to drive num }
dec al { Adjust because A: is drive 0 }
mov cx, nsects { number of sectors to Write }
mov dx, lsect { starting at sector.. }
push ds
lds bx, buffer { Get the address of the buffer }
mov bp, di
push si
int 26h { Do the drive Write. }
pop si { Remove the flags int 26h leaves on stack}
pop si
pop ds
pop di
pop bp
pop es
jc @1
mov ah, 0
@1:
mov @result, ah
end;
end;
Function absLread (drive:Char; nsects:Word; lsect:LongInt;
buffer:Pointer):Boolean;
{This Function reads sectors on disks which have the >32M style made popular}
{by Compaq Dos 3.31, MS-Dos 4+ and DR-Dos 5+. }
Var packet:Array [0..9] of Byte; {disk request packet - see Ralf Brown's ints}
begin
absLread := True;
if drive < 'A' then Exit;
if drive > 'Z' then Exit;
Asm
mov ax, Word ptr lsect {Get the LSB of the start sector}
mov Word ptr packet[0], ax {Store it in the packet }
mov ax, Word ptr lsect + 2 {Get the MSB of the start sector}
mov Word ptr packet[2], ax {Store this one too. }
mov ax, nsects {How many sectors to read }
mov Word ptr packet[4], ax
{Insert the Pointer to the data buffer into the packet}
push bp ; push ds
lds dx, buffer { Get the address of the buffer }
mov Word ptr packet[6], dx
mov dx, ds
mov Word ptr packet[8], dx
mov al, drive { Gets the passed parameter. }
and al, 1fh { Cvt from ASCII to drive num }
dec al { Adjust because A: is drive 0 }
int 25h { Do the drive read. }
pop si { Remove the flags int 25h leaves on stack}
pop ds
pop bp
jc @1
mov ah, 0
@1:
mov @result, ah
end;
end;
Function absLWrite (drive:Char; nsects:Word; lsect:LongInt;
buffer:Pointer):Boolean;
{This Function Writes sectors on disks which have the >32M style made popular}
{by Compaq Dos 3.31, MS-Dos 4+ and DR-Dos 5+. }
Var packet:Array [0..9] of Byte;
begin
absLWrite := True;
if drive < 'A' then Exit;
if drive > 'Z' then Exit;
Asm
mov ax, Word ptr lsect
mov Word ptr packet[0], ax
mov ax, Word ptr lsect + 2
mov Word ptr packet[2], ax
mov ax, nsects
mov Word ptr packet[4], ax
push bp ; push ds
lds dx, buffer
mov Word ptr packet[6], dx
mov dx, ds
mov Word ptr packet[8], dx
mov al, drive { Gets the passed parameter. }
and al, 1fh { Cvt from ASCII to drive num }
dec al { Adjust because A: is drive 0 }
int 26h { Do the drive Write. }
pop si { Remove the flags int 26h leaves on stack}
pop ds
pop bp
jc @1
mov ah, 0
@1:
mov @result, ah
end;
end;
Function LongNeeded (drive:Char):Boolean;
{This Function returns True or False depending on whether the long versions}
{of absread/absWrite needed to be invoked; that is, it's a drive Formatted }
{in the Dos 4+ >32M style. }
{I strongly suggest you see Ralf Brown's interrupt listing For int21h subfs}
{440d and 53 - they'll tell you all you know to understand the guts of this}
{Function. }
Label Escape;
Var drivestats:Array [0..31] of Byte;
begin
LongNeeded := False;
if drive < 'A' then Exit;
if drive > 'Z' then Exit;
Asm
push ds
mov dx, ss
mov ds, dx
lea dx, drivestats
mov bl, drive { Gets the passed parameter. }
and bl, 1fh { Cvt from ASCII to drive num }
mov ax, 440Dh
mov cx, 0860h
int 21h
jc Escape
mov ax, Word ptr drivestats[0Fh]
or ax, ax
jnz Escape
mov @Result, 1
Escape:
pop ds
end;
end;
begin
getmem (bp,2048);
Writeln (LongNeeded ('A'));
Writeln (LongNeeded ('C'));
Writeln (absread ('A',1,0,bp));
(* Writeln (absWrite ('A',1,2399,bp)); *) {remove the comments at your own}
{risk!!!}
freemem (bp,2048);
end.
{So I bought him a drink. The poor guy looked like he needed one....}
[Back to HARDWARE SWAG index] [Back to Main SWAG index] [Original]