Hi,
Ryu wrote:As you probably already guessed, lea eax, [ebx+ebx-7E0Ch] is not intention.
I know it looks unusual, but it actually is intentional...
The reason is that the source code mixes 32 bit assembly, unreal mode and real mode, and half of it (the POST code) operates at 0xFFFF0000 while the other half operates at 0x000F0000 (or 0xF000:0000).
The instruction itself is "lea eax, [ebx * 2 + 0xFFFF8140]", where "0xFFFF8140" is the 32 bit address of ".sE820_table" for the copy of the BIOS at 0xFFFF0000. This is because I need to use 32 bit addresses for the 32 bit code - for the 16 bit code doing something like "mov ax,.sE820_table" works perfectly because the upper bits are truncated (even though I'm using "org 0xFFFF0000").
What I really wanted to do here is "lea ax, [bx * 2 + .sE820_table]", but the CPU doesn't support this addressing mode for 16 bit instructions.
The next best option is "lea eax, [ebx*2 + (.sE820_table & 0xFFFF) ]", but NASM won't allow that - it can't do mathmatical operations on labels because it doesn't know the address that the label would end up at. Instead you get "error: `&' operator may only be applied to scalar values".
Therefore, to avoid the limitations of the CPU and the limitations of the assembler, I did it in 2 seperate instructions:
Code: Select all
lea eax,[.sE820_table+ebx*2]
and eax,0xFFFF
Another alternative would be to do it like this:
Code: Select all
lea eax,[ebx*2]
add ax,.sE820_table
As long as those extra upper 16 bits are truncated somehow you end up with the correct value in EAX at the end. I have changed it to this second version though - it'd be easier to follow a disassembly that way....
The other alternative would be to assemble the 32 bit code and the 16 bit code seperately, with "org 0x0000" for the 16 bit code and "org 0xFFFF0000" for the 32 bit code. Unfortunately that creates a lot of problems elsewhere because it's impossible to use the addresses of labels defined in one binary from another binary.
I hope this makes sense...
Cheers,
Brendan