Page 1 of 2

"Hello world" bootstrap works only on 2 of 3 PCs

Posted: Wed Jul 27, 2016 11:28 pm
by Kolodez
Hello! Maybe one of you has an idea why my bootstrap code works only on 2 of 3 PCs I've tested it on. On two of them, "Hello, world!" is printed, as I would expect, but on the third one, nothing is printed.

I've already tested the most simple bootstrap ever, namely just "int 0x10" with AX=0x0E21 and BX=0x0007. This worked on all PCs.

This is the assembler code of my bootloader, which works only on 2 of 3 PCs. What am I doing wrong? Maybe a race condition with some handler or some register not set properly? (My final aim is not to write a "hello world" bootstrap code, but something more complex for this one PC where it is not working. So I need to understand the issue and not just to make this "hello world" here working.) Thanks for your help?

Code: Select all

    cli
    xor ax, ax
    mov es, ax
    mov ss, ax
    mov ds, ax
    mov fs, ax
    mov gs, ax
    mov sp, ax
    sti
    push hello ; this is the address (0x7C34) which points to the string location
    call print_string
hang:
    jmp hang

print_string:
    push bp
    mov bp, sp
loop:
    mov bx, [bp + 4]
    mov al, [bx]
    test al, al
    jz break
    mov ah, 0x0E
    mov bx, 0x0007
    push bp ; I've read that some BIOSes have the bug to change bp after interrupt 0x10
    int 0x10
    pop bp
    inc [bp + 4]
    jmp loop
break:
    pop bp
    ret
Below, I also attach the corresponding 512 bytes if anyone has the suspition that I translated something wrong:

Code: Select all

FA 33 C0 8E C0 8E D0 8E D8 8E E0 8E E8 89 C4 FB 68 34 7C E8 02 00 EB FE 55 89 E5 8B 5E 04 8A 07 84 C0 74 0E B4 0E BB 07 00 55 CD 10 5D FF 46 04 EB E9 5D C3 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Wed Jul 27, 2016 11:57 pm
by SpyderTL
You have no way of knowing what address and segment that your BIOS used to start your boot loader code, so you have to do a far jump to a specific label before you can safely reference any other labels, like "hello".

Try something like

Code: Select all

jmp far start
start:
Also, you have to tell the compiler where this code will be located:

Code: Select all

org 7c00

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 12:02 am
by alexfru
Is the third PC at least a 386 (you're using FS and GS)? Other than that I can only see two minor issues:
* it starts with CS:IP=0x7C0:0 instead of CS:IP=0:0x7C00, which should be fine for the presented code, but you can force CS:IP to the desired value by doing a far return or an absolute far jump
* inc [bp + 4] is ambiguous (increment a byte or a word?), however from the dump it appears to be a word increment, which is correct

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 12:03 am
by alexfru
SpyderTL wrote:Also, you have to tell the compiler where this code will be located:

Code: Select all

org 7c00
It must've been omitted just like the string. The string address (the only non-PC-relative address in the code) is in the dump and is correct.

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 2:52 am
by Octocontrabass
How are you running this code on your test PCs?

Which assembler are you using?

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 7:47 am
by Kolodez
Thanks for your quick responses. Unfortunately, the problem is still present.

@SpyderTL:
Try something like "jmp far start"
I added "EA 05 00 C0 07" before the code, which means "jmp far 0x07C0:0x0005". The behaviour changed, but still not as expected (and it still works fine on the PC where it has worked before).

@alexfru:
Sure, my PC is at least i386. I have a Intel Pentium CPU G2120. You are right that my "inc [bp + 4]" should be "inc WORD PTR [bp + 4]" instead. I forgot it. ;)

What do you mean by the following? Why could this be important with different code?
it starts with CS:IP=0x7C0:0 instead of CS:IP=0:0x7C00
@Octocontrabass:
I put the byte code on a USB stick and choose it in the boot menu. As I said, this worked fine with more simple code on this PC and the code I posted here originally also goes fine on other PCs with exactly the same "testing" method.

I don't use any assembler, I translate it into binary on my own (this should be fine for a "hello world" program). ;)

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 8:00 am
by Octocontrabass
Kolodez wrote:I put the byte code on a USB stick and choose it in the boot menu. As I said, this worked fine with more simple code on this PC and the code I posted here originally also goes fine on other PCs with exactly the same "testing" method.
The BIOS might think your code is a BPB, and try to "correct" it. This corrupts the code and causes it to crash. In order to prevent this from happening, you must have exactly one of the following:
  • An actual BPB, or
  • A partition table with exactly one active partition
Kolodez wrote:I don't use any assembler, I translate it into binary on my own (this should be fine for a "hello world" program). ;)
I think you'll be better off using an assembler instead of writing machine code by hand. :roll: (I like YASM, but there are several to choose from.)

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 10:06 am
by Techel
Check the stack location.
Nope, it's fine.

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 12:00 pm
by SpyderTL
Kolodez wrote:I added "EA 05 00 C0 07" before the code, which means "jmp far 0x07C0:0x0005". The behaviour changed, but still not as expected (and it still works fine on the PC where it has worked before).
I assume you adjusted your string address when you added these bytes...

Try clearing the direction flag at the start of your code. The BIOS may be leaving it set, which will make your string print code run backwards. :)

There's also an extremely unlikely chance that your BIOS may be starting up in 32-bit mode. You can try compiling with [bits 32] and see if it works...

Also, check your BIOS settings to see if there is anything obvious that may be causing problems at startup. (Like booting in 32-bit mode...)

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 12:02 pm
by onlyonemac
Kolodez wrote:I don't use any assembler, I translate it into binary on my own (this should be fine for a "hello world" program). ;)
That is very error-prone, and time-consuming. I'm surprised that your code is actually error-free enough to work on the other PCs.

That's a compliment by the way. :-)

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 12:23 pm
by linuxyne
Kolodez wrote:I've already tested the most simple bootstrap ever, namely just "int 0x10" with AX=0x0E21 and BX=0x0007. This worked on all PCs.
Can you sprinkle that simple statement within your code to see how many dots are printed before the code goes silent? For instance, before cli, after sti, after push, after call, etc.

I assume that the system #3 does not reboot upon running your code. You can insert instructions to make the system reboot, and move the set of instructions around your code to see how far the system does reboot under your command.

Note also that 'ret' might need changing to 'ret 2', if you plan to use stack after the return.

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 12:26 pm
by Techel
Am I missing something, or is his stack location set to 0x0000:0?

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 12:31 pm
by SpyderTL
Techel wrote:Am I missing something, or is his stack location set to 0x0000:0?
Nope, your not missing anything. That's perfectly legal, assuming you have more than 1 MB of RAM.

The first time you push anything to the stack, it will roll over to 0000:fffe, and store whatever value you pushed to that address.

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 12:34 pm
by Techel
Yeah, I thought about that, but I accentially assumed it would underflow to 0xFFFF:0xFFFE :o
Well then, follow linuxyne's advice.

Re: "Hello world" bootstrap works only on 2 of 3 PCs

Posted: Thu Jul 28, 2016 1:00 pm
by Octocontrabass
Kolodez wrote:What do you mean by the following? Why could this be important with different code?
it starts with CS:IP=0x7C0:0 instead of CS:IP=0:0x7C00
Some instructions implicitly (or explicitly, with the CS: prefix) rely on the value of CS. Different PCs will boot with different values of CS. If you haven't used a far jump or some equivalent to set CS, your code will fail on some PCs. This issue doesn't affect the code you posted.
SpyderTL wrote:Try clearing the direction flag at the start of your code. The BIOS may be leaving it set, which will make your string print code run backwards. :)
The direction flag only affects string instructions, and there aren't any in this code.


If you follow linuxyne's advice, you'll discover that the corruption occurs where the disk geometry would go if you had a BPB. :wink: