I am referring BrokenThorn's OS development tutorial, and currently reading the part on developing a complete first stage bootloader that loads the second stage - Bootloaders 4.
In the part of converting Logical Block Address (LBA) to Cylinder-Head-Sector (CHS) format, this is the code that is used -
LBACHS:
xor dx, dx ; prepare dx:ax for operation
div WORD [bpbSectorsPerTrack] ; divide by sectors per track
inc dl ; add 1 (obsolute sector formula)
mov BYTE [absoluteSector], dl
xor dx, dx ; prepare dx:ax for operation
div WORD [bpbHeadsPerCylinder] ; mod by number of heads (Absolue head formula)
mov BYTE [absoluteHead], dl ; everything else was already done from the first formula
mov BYTE [absoluteTrack], al ; not much else to do :)
ret
I am not able to understand the logic behind this conversion. I tried using a few sample values to walk through it and see how it works, but that got me even more confused. Can someone explain how this conversion works and the logic used ?
I am guessing that your LBA value is being stored in
AX
as you are performing division on some value.As some pre-information for you, the
absoluteSector
is the CHS sector number,absoluteHead
is the CHS head number, andabsoluteTrack
is the CHS cylinder number. Cylinders and tracks are the exact same thing, just a different name.Also, the
DIV
operation for your code in 16-bit will take whatever is in theDX:AX
register combination and divide it by some value. The remainder of the division will be in theDX
register while the actual result will be in theAX
register.Next, the
*X
registers are 16-bit registers, where*
is one ofABCD
. They are made up of a low and high component, both referred to as*H
and*L
for high and low, respectively. For example, theDX
register hasDH
for the upper 8 bits andDL
for the lower 8 bits.Finally, as the
BYTE
andWORD
modifiers simply state the size of the data that will be used/transferred.The first value you must extract is the sector number, which is obtained by diving the LBA value by the number of sectors per track. The
DL
register will then contain the sector number minus one. This is because counting sectors starts at 1, which is different than most values, which start at zero. To fix this, we add one to theDL
register get the correct sector value. This value is stored in memory atabsoluteSector
.The next value you must extract is the head number, which is obtained by dividing the result of the last
DIV
operation by the number of heads per cylinder. TheDL
register will then contain the head number, which we store atabsoluteHead
.Finally, we get the track number. With the last division we already obtained the value, which is in the
AL
register. We then store this value atabsoluteTrack
.Hope this cleared things up a little bit.
-Adrian