Page 1 of 1

What is NASM doing with this code to break it?

Posted: Mon Jul 05, 2010 10:47 pm
by duran
Hello all,

I was playing about with the real mode keyboard interrupt code from the wiki (http://wiki.osdev.org/Keyboard#Simple_k ... _real_mode) this morning, but I couldnt get it working as is.

I assembled it as so:

nasm -f bin -o boot.img boot.asm

and then loaded it into bochs. pressed keys, nothing.

using the GUI debugger for bochs I noticed that the code entry points that nasm had resolved keyboard_handler and hex_chars to were incorrect. i modified the code to use absolute memory addresses (0x7C18 and 0x7C30, with a nop inserted after jmp $ for alignment purposes). After this, all worked hunky dory.

What i don't understand is, why did Nasm assemble this using such seemingly arbitrary addresses?

i've noticed this same behaviour using other code written by myself, but i assumed it was something silly that i must have been doing. this isn't my code though and seems to be doing the same thing.


EDIT: It appears as though this is a bug in the Nasm 2.09rc1 binary hosted on the nasm home page. the code assembles correctly using the Ubuntu Hardy nasm.

Re: What is NASM doing with this code to break it?

Posted: Tue Jul 06, 2010 1:46 am
by Candy
Your BIOS may use 0x7C0:0x0000 as target instead of 0x0000:0x7C00. That causes your ORG to be messed up & all the jumps to go haywire.

Normalize the segment by a long jump at the start of your code first.

Re: What is NASM doing with this code to break it?

Posted: Tue Jul 06, 2010 6:51 am
by qw
Candy wrote:Your BIOS may use 0x7C0:0x0000 as target instead of 0x0000:0x7C00. That causes your ORG to be messed up & all the jumps to go haywire.

Normalize the segment by a long jump at the start of your code first.
If NASM does not assign the right absolute address to a symbol, than long jumping won't help.

Anyway, I compiled with NASM 2.08 with no problems.

Duran, what were the incorrect addresses that you got first?

Re: What is NASM doing with this code to break it?

Posted: Tue Jul 06, 2010 10:49 am
by Love4Boobies
Yes it will since 07C0:0000 and 0000:7C00 resolve to the same physical address. The problem isn't with relative jumps but short jumps - a long jump will make sure that all short jumps work for your given origin.

Re: What is NASM doing with this code to break it?

Posted: Tue Jul 06, 2010 11:07 am
by Firestryke31
According to the comments in the bug report on the NASM site, this was in fact a bug with NASM. Jumping to a equivalent segment would not have fixed it as NASM was flat out wrong (0x9300s instead of 0x7c00s).

http://sourceforge.net/tracker/?func=de ... tid=106208

Re: What is NASM doing with this code to break it?

Posted: Tue Jul 06, 2010 11:09 am
by Owen
Love4Boobies wrote:Yes it will since 07C0:0000 and 0000:7C00 resolve to the same physical address. The problem isn't with relative jumps but short jumps - a long jump will make sure that all short jumps work for your given origin.
Short jumps will work irrespective of where your code is compiled. Remember: x86 doesn't have an absolute near jump instruction.

Re: What is NASM doing with this code to break it?

Posted: Tue Jul 06, 2010 10:34 pm
by Candy
Firestryke31 wrote:According to the comments in the bug report on the NASM site, this was in fact a bug with NASM. Jumping to a equivalent segment would not have fixed it as NASM was flat out wrong (0x9300s instead of 0x7c00s).
Wow... That doesn't happen often, that finding an error in your code execution ends up in finding a bug in the compiler/assembler.

Do wonder what mistake this is when the same code base messes up on Windows and runs fine on Ubuntu.

Re: What is NASM doing with this code to break it?

Posted: Tue Jul 06, 2010 11:47 pm
by Love4Boobies
Owen wrote:
Love4Boobies wrote:Yes it will since 07C0:0000 and 0000:7C00 resolve to the same physical address. The problem isn't with relative jumps but short jumps - a long jump will make sure that all short jumps work for your given origin.
Short jumps will work irrespective of where your code is compiled. Remember: x86 doesn't have an absolute near jump instruction.
Maybe an example will help...

1) BIOS origin is 07C0:0000 but the boot sector expects 0000:7C00.
2) Next, the boot code attempts a near absolute jump (e.g., jump to offset 7C50h) - those who have read Owen's post, see PS.
3) The jump will be made to 07C0:7C50, which doesn't resolve to the same physical address as 0000:7C50.

However, doing a far jump at the beginning of the boot code will ensure that CS has the value you expect.

PS: I didn't mean "short jumps" in the previous post, my bad. Near absolute is indeed possible on the x86, but not with immediate values.

Re: What is NASM doing with this code to break it?

Posted: Wed Jul 07, 2010 9:11 am
by Gigasoft
Hm, it turns out that my FAT12 boot sector does use absolute code addresses. But, I have only 4 bytes to spare, not enough for a far jump. Perhaps my boot sector is trying to do too much? It provides services to the OS for loading files during the boot process (before drivers have been loaded and hardware has been taken over), and it also handles long filenames and subdirectories.

Re: What is NASM doing with this code to break it?

Posted: Wed Jul 07, 2010 9:13 am
by Love4Boobies
Attach your boot sector here. I am almost entirely sure we can make your code a lot more compact. :)

Re: What is NASM doing with this code to break it?

Posted: Wed Jul 07, 2010 1:04 pm
by Gigasoft
Oh, wait, I was mistaken. I had more bytes to spare than I thought, so it worked out fine.

I'll post it anyway, so perhaps someone can help improve it even further? It is currently untested, so I apologize for any mistakes that may be present.

(This file is in MASM syntax, and is assembled into OMF format, which my custom made linker expects.)