How to Read and Write to a Hard Drive
Written by Jack Dobiash
Since I've been getting several questions regarding how to access the data on a Hard Drive, I figured I'd write up this little starter. I don't plan on showing every detail, since each programming language has a different way to implement it, but it should at least point you in the right direction. Basically all these instructions pertain to using the Software Interrupts that are built into DOS v5.0 and above, including Windows '95 and '98 (Although I don't use any that require me to be inside of the GUI environment). Note that this may not be (and probably isn't) the only way to do this, but it is the method that I am using. If you have a different operating system than something Microsoft based, while the Interrupts may be different, the method to doing it is still probably similar.
Int 13h Extensions
Right off the bat I have to talk about the Int 13h Extensions. Basically Interrupt 13h is the one that I use for all of the disk accessing. The problem is that the original disk accessing commands of Int 13h don't have the capability of reaching beyond the 8GB barrier which some of you have probably heard of. The limit stems from the fact that they only allow a maximum of 1024 cylinders, 256 heads, and 63 sectors per track, which if you multiply those all together and then by 512 (number of bytes in each sector), you get the 8GB (Actually it's a tad below 8GB, but pretty darn close). Anyway, newer computers have BIOS's that have Int 13h Extensions in them, which are new routines that can reach beyond the barrier. Older computers which don't have this addition can have a Disk Overlay Manager (like OnTrack or EZ-Drive) load up right at the start which will add in routines and make the whole drive accessible. There were also other barriers too (the 504MB limit, the 2048MB limit) but those were for other reasons.
Basically the first thing you want to do is check to see if the computer has the capability to use the Int 13h Extensions. If it does, you can then just use those routines from that point on, otherwise you'll need to use the older ones. The Interrupt to check for the extensions is Int 13h, section AH=41h. If the Carry Flag is NOT set, then the computer has the extensions.
Note: Here is a link to all of the interrupts I'm going to talk about on this page, with information on what to plug into the Registers to make them work. Since talking about the details of how to use each interrupt would take to long, I'll just say which ones to use and you can refer to the Interrupts Page on how to use them.
So from now on I'll make two references on how to do things. One with the extensions, and one without.
To support disk drives larger than 137 GB, modern BIOSs
have extensions for "48-bit LBA" (a/k/a "LBA48") disk
access. The specifications are here:
(Thanks to Dave Burton for this Information!)
First thing that needs to be done is to get the parameters of the drive (How many Cylinders, Head, Sectors, Total # of Sectors, etc).
: Use Int 13h, section AH=48h.
Non-Extensions Method : Use Int 13h, section AH=08h.
The Non-Extensions Method won't give you the Total # of Sectors in the drive, so if you need to know you'll have to calculate it. Also, the values you get from the Extensions Method are the TOTAL amount of them, so if it says you have 128 heads, it means you have to use 127 as the Max Value, since Heads and Cylinders are 0 based values. The number of sectors will be correct as is, since it is a 1 based value.
CHS <--> LBA Translations
If you can use Extensions, than basically you won't need to use anything but LBA (Logical Block Addressing) Mode. In this mode you can just reference the drive sector by sector, with 0 being the MBR, and on up. No need to keep track of what Cylinder or Head or Sector you are on that way. If you can't use the extensions, then you'll need routines to convert an LBA value into a CHS value in order to use the reading and writing routines. It's still a good idea to reference everything in LBA, and to only use CHS when doing the actual reading and writing. For example, if I want to access the 16000th sector through the 17000th sector of a hard drive, instead of having to keep track of CHS values during the count, you just use LBA, and send that number to the read/write routine, which at that point the LBA gets turned into CHS to be used in the interrupt. It's must easier than having to keep track of incrementing H when S is full and incrementing C when H is full.
Anyway, onto the math. To Convert a CHS value to a LBA value, you use this math formula:
LBA = (Sector - 1) + (Head * Total Sectors) + (Cylinder * (Total Heads + 1) * Total Sectors)
Total Sectors and Total Heads were values obtained from the Drive Parameters.
To Convert an LBA value back to CHS, you use these math formulas:
= ((LBA Mod Total Sectors) +1)
CylHead = (LBA Div Total Sectors)
Head = (CylHead Mod (Total Heads + 1))
Cylinder = (CylHead Div (Total Heads + 1))
Basically what you are seeing here is how I did it in Pascal without some of the syntax. MOD is a way to obtain the remainder of the math, instead of the quotient. You'll need to figure out what your languages equivalent syntax is. Also, CYLHEAD is just a temporary variable I used to hold information which was then used to figure out the # of Heads and Cylinders.
: Use Int13h, section AH=42h
Non-Extensions Method : Use Int13h, section AH=02h
: Use Int13h, section AH=43h
Non-Extensions Method : Use Int13h, section AH=03h
Editing the Drive
I've also gotten some questions regarding how to directly edit your drive. In response I've decided to release my own little Disk Doctor program. Basically it allows you to go through the sectors of your hard drive and make byte by byte changes. Of course this is a USE AT YOUR OWN RISK program, but I use it at work and it helps me to figure out what has happened to a hard drive.
Well, that's about it! Check out the Interrupts Page for a listing of all the Interrupts shown in this document.