LBA to CHS

LBA to CHS

This is a (very) simple LBA to CHS tutorial. I assume that you know how to Add, Subtract, Divide and multiply and that you know what Assembly is and possibly the basics of it. (though I go over the basics to remind you in case you have forgotten)

Brief idea of what the physical drive is like:

A normal floppy drive (which I will use for this example) contains 2 main parts.Sector: The area on the diskCylinder: aka Track, one circle at the same radius from the center.Head: The top or bottom side of the disk? (In hard disks you have multiple magnetic disks) Also it is the head that contains the mechanism to read and write to the disk.

So to address any part of the drive you have to say:1. Top or bottom2. How far to move the head from the center3. How far to move the disk round.

Ok so what is LBA?

LBA is logical addressing of your physicial drive.Or in simple terms you refer to sectors on the floppy or hard disk as 1,2,3,4,5,.....

Ok so what is CHS?

CHS is the method the drive uses to load sectors from the floppy or hard disk.This composes of a Sector, Cylinder, Head.

Maths!!!

If you are anything like me you will shudder at the notion of maths. In order to understand this you will have to know at least basic division, which is not to hard.

If you look at most sites they will give you this set of formulas:Sector = (LBA mod SectorsPerTrack)+1Cylinder = (LBA/SectorsPerTrack)/NumHeadsHead = (LBA/SectorsPerTrack) mod NumHeads

Is there a different way?

Well this is the only formula which works so don't go looking for any other way to do this, as an easier doesn't exist.

So what does it all mean?

mod stands for modulus in the formulas I presented./ stands for divide.

An easy way I've decided to look at the mod's is as points to take the remainder value rather than the quotient value.

(The plus 1 on the sectors is because you need a sector to read at least, else you won't be reading anything if theres a 0 anywhere, for some reason they don't start at 0 or something like that, but miss it out and out and you will have interesting things happen)

The vague algorithm:

Assembly Language introduction:

ASM terms:Registers - In simple terms memory/variables of a fixed size in the CPU - In the code I'm writing the size is 16 bytes for each register.

ASM commands used:The DIV command is very important in this function.DIV ; Divides register AX by the register you enter as reg ; Output value AX = Quotient DX = Remainder.The MOV command is simple but used often.MOV ; Move the Source to the destination.The INC command is again simple but is needed.INC ; Adds 1 to the register you pass to the command.The XOR command is mostly used for turning a register to zero's. It compares each bit of two registers and if they are set the same outputs zero as the result.XOR ax, ax ; This will zero ax (will work with any register)The RET command is used to return to the main program.RET ; Returns to the main programPUSH ; Puts the register's value onto the stackPOP ; Restores a registers value using the value on the stack

In order to learn more about Asm I suggest looking at the Art Of Asm website (The location changes and this may not be updated regularly so best to look for it in a search engine) The book 'Assembly Language Step By Step' By Jeff Duntemann is also very usefull for beginners to Assembly Language programming.

And to find out more about the commands I put up look at the Intel Reference manual, also the NASM documentation has a reference section. (Quite likely similar documentation is also around else where)

Simple Assembly example:

(This is not likely to work if you cut and paste it and is here to show the principle only, look at the next section for a complete example)

LBACHS:
; Set up the registers ready for the divide
MOV ax, [LBAvalue] ; []'s means value at memory location LBAvalue.
; Make the divide
DIV [SectorsPerTrack] ; Carry out the division of ax.
; Put the returned Number Of Tracks some where
MOV [NumTracks], ax ; Put the quotient into a memory variable
; Sort out the sector value
INC dx ; Add 1 to the remainder
MOV [Sector], dx ; Put the remainder into a memory variable
; Set up the registers ready for the divide
MOV ax, [NumTracks] ; Put the number of tracks in to ax
; Make the divide
DIV [NumHeads] ; Divide NumTracks (ax) by NumHeads
; Stash the results in some memory locations
MOV [Cylinder], ax ; Quotient value, the Number of heads to be moved from ax
MOV [Head], dx ; Remainder value, the cylinder value to be oved from dx

Advanced Assembly example:

(This will most likely work, but like any of my code I can't say for certain, being to lazy to test it at the time of writing this tutorial)

If you want to see new things in here please say, if you want to translate this into an other language please send me the new version so I can host that as an alternative. (I can translate copy's of this if requested but the altavista translater isn't quite perfected for large documents like this, and I would rather spend my time working on something else)

This tutorial is here with the permission of Daniel Faulkner, if you wish to put this tutorial on another site, please contact Daniel for permission.