{ These two functions allow you to call MS-DOS interrupts 25H and 26H. They can't be called with Turbo Pascal's built in Intr procedure because they leave the flags register on the stack, in violation of 8086 programming techniques. Interrupt 25H is called Absolute Disk Read, while 26H is Absolute Disk Write. The functions ReadSectors and WriteSectors respectively allow you to call these interrupts. This provides a very low level interface to the disk drives. Because of this, THESE FUNCTIONS SHOULD BE USED WITH EXTREME CAUTION, and only if you are sure you know what you are doing. Both functions are called with the same parameters: Buffer: a buffer large enough to hold NumberSectors 512 byte sectors. Drive: the drive number. 0 is A:, 1 is B:, and so on. NumberSectors: the number of sectors to transfer. LogicalSector: the first logical sector number to transfer. Be sure that Buffer is large enough to hold 512*NumberSectors bytes of data. Failure to do so will surely lead to bugs that are difficult to solve. The integer return value is the error code returned by MS-DOS. 0 indicates a successful transfer. All other values are errors; see a DOS Technical Reference Manual for translations. A small example program is provided. It is a minimal disk editor and is intended as an example only, though it provides the basis for a complete disk editor/utility. (This is a challenge to you hackers). The example is commented out -- you must remove the line with the (* on it. - Bela Lubkin 71016,1573 5/28/85 } {*$C-} { Remove the leading * for better keyboard response in the example program } Function __ReadWriteSectors(Var Buffer; Drive, NumberSectors, LogicalSector: Integer; WriteFlag: Byte): Integer; Var Result: Integer; Begin Result:=0; Inline($8A/$86/ Drive / { MOV AL,[BP+Drive] } $8B/$8E/ NumberSectors / { MOV CX,[BP+NumberSectors] } $8B/$96/ LogicalSector / { MOV DX,[BP+LogicalSector] } $55/ { PUSH BP } $1E/ { PUSH DS } $C5/$9E/ Buffer / { LDS BX,[BP+Buffer] } $80/$BE/ WriteFlag /$01/ { CMP BYTE PTR [BP+WriteFlag],1 } $74/$04/ { JE Write } $CD/$25/ { INT 25H } $EB/$02/ { JMP WrapUp } $CD/$26/ {Write: INT 26H } $5B/ {WrapUp:POP BX ;Dispose of flags } $1F/ { POP DS } $5D/ { POP BP } $73/$04/ { JNB Ok } $89/$86/ Result { MOV [BP+Result],AX } ); {Ok: } __ReadWriteSectors:=Result; End; Function ReadSectors(Var Buffer; Drive, NumberSectors, LogicalSector: Integer): Integer; Begin ReadSectors:= __ReadWriteSectors(Buffer,Drive,NumberSectors,LogicalSector,0); End; Function WriteSectors(Var Buffer; Drive, NumberSectors, LogicalSector: Integer): Integer; Begin WriteSectors:= __ReadWriteSectors(Buffer,Drive,NumberSectors,LogicalSector,1); End; { Example program. Delete next line to enable it: } (* {$R+} Type Str=String[4]; Function Int2Hex2(B: Byte): Str; Const H: Array [0..15] Of Char='0123456789ABCDEF'; Begin Int2Hex2:=H[B Shr 4]+H[B And 15]; End; Function Int2Hex4(I: Integer): Str; Const H: Array [0..15] Of Char='0123456789ABCDEF'; Begin Int2Hex4:=H[I Shr 12]+H[(I Shr 8) And 15]+H[(I Shr 4) And 15]+H[I And 15]; End; Function Hex2Int1(C: Char): Byte; Begin Case Upcase(C) Of '0'..'9': Hex2Int1:=Ord(C) And 15; 'A'..'F': Hex2Int1:=Ord(C) And 15+9; Else Hex2Int1:=0; End; End; Function Hex2Int4(S: Str; Default: Integer): Integer; Var I: Integer; Begin If S='' Then Hex2Int4:=Default Else Begin I:=0; While S<>'' Do Begin I:=I Shl 4 + Hex2Int1(S[1]); Delete(S,1,1); End; Hex2Int4:=I; End; End; Procedure ShowSector(Var S); Var Buffer: Array [0..31,0..15] Of Byte Absolute S; I,J: Integer; B: Byte; Begin For I:=0 To 31 Do Begin Write(Int2Hex4(I Shl 4),' | '); For J:=0 To 15 Do Begin Write(Int2Hex2(Buffer[I,J]),' '); If J And 3=3 Then Write(' '); End; Write('| '); For J:=0 To 15 Do Begin B:=Buffer[I,J]; If B<127 Then NormVideo Else LowVideo; B:=B And $7F; If B<32 Then B:=Ord('.'); Write(Chr(B)); End; NormVideo; WriteLn; End; End; Var Buffer: Array [0..511] Of Byte; DR,LS,Result,C: Integer; W: Char; V: Str; Changed: Boolean; Begin FillChar(Buffer,SizeOf(Buffer),'z'); Repeat DR:=-1; Write('Enter the drive # to read (CR to end): '); ReadLn(DR); If DR In [0..25] Then Begin Write('Enter the logical sector # to read: '); ReadLn(LS); Result:=ReadSectors(Buffer,DR,1,LS); WriteLn('Result code = ',Result); Changed:=False; Repeat ShowSector(Buffer); Write('Enter the number of the byte to change (0-1FF, CR to end): '); ReadLn(V); C:=Hex2Int4(V,-1); If (C>0) And (C<512) Then Begin Write('Enter new value [',Int2Hex2(Buffer[C]),']: '); ReadLn(V); If Length(V)>1 Then If V[1] In ['''','"'] Then Buffer[C]:=Ord(V[2]) Else Buffer[C]:=Hex2Int4(V,Buffer[C]) Else Buffer[C]:=Hex2Int4(V,Buffer[C]); Changed:=True; End Else C:=-1; Until C=-1; If Changed Then Begin Write('Write changes back to drive ',DR,', logical sector #',LS,' (Y/N)? '); ReadLn(W); If Upcase(W)='Y' Then Begin Result:=WriteSectors(Buffer,DR,1,LS); WriteLn('Result code = ',Result); End; End; End Else DR:=-1; Until DR=-1; End. (**)