CHS and LBA Confusion

Programming, for all ages and all languages.
Post Reply
sds2017
Member
Member
Posts: 61
Joined: Tue Jul 05, 2011 10:05 am

CHS and LBA Confusion

Post by sds2017 »

Hello I've been building a bootloader and I've looked for code showing how to convert LBA(Liogical Block Addressing) to CHS(Cylinder, Head, Sector) and CHS to LBA(BTW I'm using FAT12). I found this code and I just don't understand the way they did this.
The formula to convert CHS to LBA:

Code: Select all

CHS to LBA
Formula    
    LBA = (cluster - 2 ) * sectors per cluster
And here the code:
          
          sub     ax, 0x0002                          ; subtract 2 from cluster number
          xor     cx, cx
          mov     cl, BYTE [bpbSectorsPerCluster]     ; get sectors per cluster
          mul     cx                                                   ;Why multiply by cx? Why not ax?

LBA to CHS
Formula:
      absolute sector 	= 	(logical sector / sectors per track) + 1
      absolute head   	= 	(logical sector / sectors per track) MOD number of heads
      absolute track 	= 	 logical sector / (sectors per track * number of heads)
Code:
    LBACHS:
          xor     dx, dx                                           
          div     WORD [bpbSectorsPerTrack]           
          inc     dl                                                   
          mov     BYTE [absoluteSector], dl               
 
          xor     dx, dx                                          
          div     WORD [bpbHeadsPerCylinder]       
          mov     BYTE [absoluteHead], dl            
 
          mov     BYTE [absoluteTrack], al            
          ret
Shouldn't the code be look this:

Code: Select all

xor dx, dx
div WORD [bpbSectorsPerTrack]
push dx
inc dx
mov BYTE [absoluteSector]
pop dx
;Then somehow get the MOD
mov  BYTE[absoluteHead], dx
mov dx, WORD [bpbSectorPerTrack]
mul BYTES [bpbNumberOfHeads]
xor ax, ax
div dx
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Mul Confusion

Post by Combuster »

mul cx ;Why multiply by cx? Why not ax?
As far as I know, a multiplication requires two numbers. What is multiplied by cx? Right, it's the ax you can't see.

Do you have a copy of intel manuals, volume 2? You should read it.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
sds2017
Member
Member
Posts: 61
Joined: Tue Jul 05, 2011 10:05 am

Re: CHS and LBA Confusion

Post by sds2017 »

Thank you for your reply and I'll look into intel manuals, volume 2 but, I don't understand what your explanation mean ""Right, its the ax you can't see". I thought your supposed to multiply ax by cl but, instead the multiply cl by cx. Am I right? Correct me if I'm not.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: CHS and LBA Confusion

Post by Combuster »

It does just that:
mul cx ; multiply ax (implied) with cx, store result in ax:dx (again implied)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
sds2017
Member
Member
Posts: 61
Joined: Tue Jul 05, 2011 10:05 am

Re: CHS and LBA Confusion

Post by sds2017 »

Thanks. I just was confused. I thought that cx was multiplied by cl. I guess if you move a number into a register and you multiply that register that it applies to another register.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: CHS and LBA Confusion

Post by Brendan »

Hi,
sds2017 wrote:The formula to convert CHS to LBA:

Code: Select all

CHS to LBA
Formula    
    LBA = (cluster - 2 ) * sectors per cluster
And here the code:
          
          sub     ax, 0x0002                          ; subtract 2 from cluster number
          xor     cx, cx
          mov     cl, BYTE [bpbSectorsPerCluster]     ; get sectors per cluster
          mul     cx                                                   ;Why multiply by cx? Why not ax?
That doesn't convert CHS into LBA. It converts a FAT "cluster number" into an LBA.

"mul cx" actually does "dx:ax = ax * cx", and gives a 32-bit unsigned integer (in DX:AX) as a result.
sds2017 wrote:

Code: Select all

LBA to CHS
Formula:
      absolute sector 	= 	(logical sector / sectors per track) + 1
      absolute head   	= 	(logical sector / sectors per track) MOD number of heads
      absolute track 	= 	 logical sector / (sectors per track * number of heads)
That formula looks wrong to me. It should be:

Code: Select all

      absolute sector 	= 	(logical sector MOD sectors per track) + 1
      absolute head   	= 	(logical sector / sectors per track) MOD number of heads
      absolute track 	= 	 logical sector / (sectors per track * number of heads)
You can rearrange it like this:

Code: Select all

      quotient1 = logical sector / sectors per track
      remainder1 = logical sector MOD sectors per track
      absolute sector = 	remainder1 + 1
      quotient2 = quotient1 / number of heads
      remainder2 = quotient1 MOD number of heads
      absolute head = remainder2
      absolute track =  quotient2
Note that the DIV instruction gives you the quotient and the remainder (which is why I did the "quotient1" and "remainder1" thing - you get both from one division). For e.g. "AX = DX:AX / divisor; DX = DX:AX MOD divisor".

Here's the original code with comments added:

Code: Select all

Input:
 AX = LBA address (why not DX:AX?)

Code:
    LBACHS:
          xor     dx, dx                          ;dx:ax = LBA address                   
          div     WORD [bpbSectorsPerTrack]       ;dx = LBA address MOD sectors per track
                                                  ;ax = LBA address / sectors per track
          inc     dl                              ;dl =  LBA address MOD sectors per track + 1
          mov     BYTE [absoluteSector], dl       ;Sector = LBA address MOD sectors per track + 1
 
          xor     dx, dx                          ;dx:ax = LBA address / sectors per track
          div     WORD [bpbHeadsPerCylinder]      ;dx = (LBA address / sectors per track) MOD heads per cylinder
                                                  ;ax = (LBA address / sectors per track) / heads per cylinder
          mov     BYTE [absoluteHead], dl         ;Head = (LBA address / sectors per track) MOD heads per cylinder
          mov     BYTE [absoluteTrack], al        ;Track = (LBA address / sectors per track) / heads per cylinder
          ret
You can see that it does implement the corrected version of the formulas (but didn't implement the original/wrong version of those formulas).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: CHS and LBA Confusion

Post by egos »

To use 32-bit LBA for division you should imlement "double division" operation because the quotient after "single division" can be > 65535.
Brendan wrote:That doesn't convert CHS into LBA. It converts a FAT "cluster number" into an LBA.
It's "LBA" within data area. Don't forget about hidden sectors, reserved sectors, FATSize*FATs sectors and root sectors (FAT1x).

sds2017, there is no reason to convert CHS to LBA at all.
If you have seen bad English in my words, tell me what's wrong, please.
sds2017
Member
Member
Posts: 61
Joined: Tue Jul 05, 2011 10:05 am

Re: CHS and LBA Confusion

Post by sds2017 »

Thank you now I completely understand it.
Post Reply