Mixing 32 bit calculation in 16 bit program NASM

Programming, for all ages and all languages.
Post Reply
dumbterminal
Posts: 4
Joined: Sun Dec 19, 2010 6:52 am

Mixing 32 bit calculation in 16 bit program NASM

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Mixing 32 bit calculation in 16 bit program NASM

Post 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
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.
Post Reply