' This first solution is suitable for *older* computers with ' a hard drive smaller than 8.4 GB and old BIOS ' $INCLUDE: 'qb.bi' TYPE SectorBuffer Inh AS STRING * 512 END TYPE DIM dosIntEin AS RegTypeX, dosIntAus AS RegTypeX DIM sb AS SectorBuffer ' Reading INPUT "Hard drive number (0=1st C:\ drive, 1=2nd D:\ drive)"; n% INPUT "Cylinder # (0-1023)"; c% INPUT "Head # (0-255)"; h% INPUT "Sector # (0-63)"; s% dosIntEin.ax = &H201 ' Function 02h, 1 Sector dosIntEin.dx = CVI(CHR$(128 + n%) + CHR$(h%)) ' DH=Head, DL=drive # dosIntEin.cx = CVI(CHR$(c% AND 255) + CHR$((c% AND 768) \ 4 + s%)) ' ^_This is a little more complicate because Bit 8 and 9 of the cylinder ' number are stored as CL's bit 6 and 7 dosIntEin.es = VARSEG(sb) dosIntEin.bx = VARPTR(sb) ' Do this read operation CALL INTERRUPTX(&H13, dosIntEin, dosIntAus) ' Check if operation has been done successfully IF dosIntAus.flags AND 1 THEN ' Check Carry flag PRINT "An error occured. Code="; ASC(RIGHT$(MKI$(dosIntAus.ax), 1)) END END IF ' Do a hexdump FOR i% = 0 TO 496 STEP 16 h$ = HEX$(i%) PRINT STRING$(4 - LEN(h$), "0"); h$; " :"; FOR j% = 1 TO 16 h$ = HEX$(ASC(MID$(sb.Inh, i% + j%, 1))) PRINT " "; STRING$(4 - LEN(h$), "0"); h$; NEXT j% PRINT NEXT i% ' Copy this sector to another place INPUT "Hard drive number (0=1st C:\ drive, 1=2nd D:\ drive)"; n% INPUT "Cylinder # (0-1023)"; c% INPUT "Head # (0-255)"; h% INPUT "Sector # (0-63)"; s% dosIntEin.ax = &H301 ' Function AH=03h, 1 sector dosIntEin.dx = CVI(CHR$(128 + n%) + CHR$(h%)) ' DH=Head, DL=drive # dosIntEin.cx = CVI(CHR$(c% AND 255) + CHR$((c% AND 768) \ 4 + s%)) ' ^_This is a little more complicate because Bit 8 and 9 of the cylinder ' number are stored as CL's bit 6 and 7 dosIntEin.es = VARSEG(sb) dosIntEin.bx = VARPTR(sb) ' Do this write operation CALL INTERRUPTX(&H13, dosIntEin, dosIntAus) ' Check if operation has been done successfully IF dosIntAus.flags AND 1 THEN ' Check Carry flag PRINT "An error occured. Code="; ASC(RIGHT$(MKI$(dosIntAus.ax), 1)) END END IF ' Demo 2: LBA ' ----------------------------------------------------------------- ' If you own a hard drive larger than 8.4 GB and a modern BIOS, it ' needs using the INT 13h Extensions defined by IBM and Microsoft, ' well-known as large buffer addressing mode (LBA) ' In this model, all sectors are linearly ordered like a big array ' variable. This simplifies handling dramatically TYPE diskAddressPacket size AS STRING * 1 reserv AS STRING * 1 nBlk AS INTEGER tBufOffs AS INTEGER tBufSeg AS INTEGER absBlkNumLo AS LONG absBlkNumHi AS LONG END TYPE DIM dap AS diskAddressPacket INPUT "Hard drive number (0=1st C:\ drive, 1=2nd D:\ drive)"; n% ' First we check the BIOS's INT 13h Extension capability dosIntEin.ax = &H4100 ' Function AH=41h: Installation check dosIntEin.bx = &H55AA dosIntEin.dx = 128 + n% CALL INTERRUPTX(&H13, dosIntEin, dosIntAus) IF (dosIntAus.flags AND 1) = 1 OR dosIntAus.bx <> &HAA55 THEN PRINT "Error: BIOS INT 13h Extension not supported" END END IF ' Important note: The address is represented as a 64 bit number ' this means that you can address theoretically 2^73 bytes or ' 8 septillions of bytes!! For simplification, we only ask a ' 32 bit number. For the today's hard drives it's sufficient but in ' the future we may need to provide all 64 bits. This simplification ' saves develop a big number arithmetic inside QuickBASIC INPUT "Block number"; blk& dap.size = LEN(dap) dap.reserv = 0 dap.nBlk = 1 ' one sector dap.tBufOffs = VARPTR(sb) ' same buffer from the C/H/S demo dap.tBufSeg = VARSEG(sb) dap.absBlkNumLo = blk& dap.absBlkNumHi = 0& ' see notice! dosIntEin.ax = &H4200 ' Function AH=42h dosIntEin.dx = 128 + n% dosIntEin.ds = VARSEG(dap) dosIntEin.si = VARPTR(dap) ' Do this LBA read operation CALL INTERRUPTX(&H13, dosIntEin, dosIntAus) ' Check if operation has been done successfully IF dosIntAus.flags AND 1 THEN ' Check Carry flag PRINT "An error occured. Code="; ASC(RIGHT$(MKI$(dosIntAus.ax), 1)) END END IF ' Do a hexdump too FOR i% = 0 TO 496 STEP 16 h$ = HEX$(i%) PRINT STRING$(4 - LEN(h$), "0"); h$; " :"; FOR j% = 1 TO 16 h$ = HEX$(ASC(MID$(sb.Inh, i% + j%, 1))) PRINT " "; STRING$(4 - LEN(h$), "0"); h$; NEXT j% PRINT NEXT i% ' Write this sector on another place INPUT "Hard drive number (0=1st C:\ drive, 1=2nd D:\ drive)"; n% INPUT "Block number"; blk& dap.size = LEN(dap) dap.reserv = 0 dap.nBlk = 1 ' one sector dap.tBufOffs = VARPTR(sb) ' same buffer from the C/H/S demo dap.tBufSeg = VARSEG(sb) dap.absBlkNumLo = blk& dap.absBlkNumHi = 0& ' see same notice like in the read demo! dosIntEin.ax = &H4300 ' Function AH=43h, do it without verify dosIntEin.dx = 128 + n% dosIntEin.ds = VARSEG(dap) dosIntEin.si = VARPTR(dap) ' Do this LBA write operation CALL INTERRUPTX(&H13, dosIntEin, dosIntAus) ' Check if operation has been done successfully IF dosIntAus.flags AND 1 THEN ' Check Carry flag PRINT "An error occured. Code="; ASC(RIGHT$(MKI$(dosIntAus.ax), 1)) END END IF