Page 1 of 1

Mixing 32 bit calculation in 16 bit program NASM

Posted: Tue Dec 28, 2010 2:11 pm
by dumbterminal
I am a n00b in this case, and really don't know how to do it. so it would be great if u kindly show me the right way to do it.
For instance the following instructions provides wrong result, how to make it right ?? (i heard something of 0x66 prefix and incase of address 0x67 -- but how to use them ??)
Code:

Code: Select all

;; just to remind you [BITS 16]
AND EAX, 0x0000FFFF
SUB EAX, 2
XOR ECX, ECX
MOV CL, [SectorsPerCluster]
MUL ECX
ADD EAX, DWORD [DataAreaStart]
ADD EAX, [LBAStart]
;MOV EAX, 969434
MOV [DAP + 8], EAX
CALL ReadSectorsLBA_
Rest of my code is right coz the result (EAX after those instruction) should be 969434 and if i put it directly it gives desired result. But the formula isn't wrong either, plz help me understand mixing up 32 Bit calculation in 16 bit program.
The formula i am using is
LBA_addr = offset_from_partition_table + DataAreaStart + (cluster_no - 2) * sectors_per_cluster
In my code
offset_from_partition_table = LBAStart
DataAreaStart = DataAreaStart
cluster_no = AX
sectors_per_clusetr = SectorsPerCluster

Just assume other values of my bootloaders are correct, i have tested it.
U c the Sector Number field of DAP and the LBAStart is both DWORD so had no way but resort to EAX.
Regards and thanx in advance.

Re: Mixing 32 bit calculation in 16 bit program NASM

Posted: Thu Jan 06, 2011 5:59 pm
by Brendan
Hi,

That code looks entirely correct to me. It could be better commented (and a little more concise), like this:

Code: Select all

;; just to remind you [BITS 16]

; LBA_addr = offset_from_partition_table + DataAreaStart + (cluster_no - 2) * sectors_per_cluster

    movzx eax,ax                       ;eax = cluster_no
    sub eax,2                          ;eax = cluster_no - 2
    movzx ecx,byte [SectorsPerCluster] ;ecx = sectors_per_cluster
    mul ecx                            ;edx:eax = (cluster_no - 2) * sectors_per_cluster
    add eax,[DataAreaStart]            ;eax = DataAreaStart + (cluster_no - 2) * sectors_per_cluster
    add eax, [LBAStart]                ;eax = offset_from_partition_table + DataAreaStart + (cluster_no - 2) * sectors_per_cluster
    mov [DAP + 8], eax
    CALL ReadSectorsLBA
But that won't give you different results.

It's also impossible for the calculation to overflow a 32-bit unsigned integer until after the MUL (so it doesn't matter that EDX from the MUL is ignored/discarded). It is possible for those additions to cause overflows though, but if the correct answer is 969434 and if DataAreaStart and LBAStart are both correct, then that can't be your problem either.

This code is right, therefore some assumption you've made is wrong. Either the initial value in EAX (cluster_no) is wrong, the formula is wrong, the values it's using for SectorsPerCluster, DataAreaStart and LBAStart are wrong, or the sizes of the values are wrong (e.g. 16-bit DataAreaStart or something). :)

I'd suggest single-stepping in a debugger (e.g. the debugger built into Bochs) and seeing exactly what does happen. For all I know it could be something like DS not set properly...


Cheers,

Brendan