Search code examples
assemblyx86nasmbootloaderbios

Why doesn't this boot loader code work?


My expectation is that it prints a string, but nothing is printed out. When I make the string shorter, it sometimes works, and when I make them longer again, it works sometimes.

I don't know why this isn't working.

Could somebody help me? Thanks.

The assembly code I'm using is:

(Emacs 23, Ubuntu 10.10, nasm, VirtualBox OSE)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0x7c00
bits 16
str:
    db "Some say the world will end in fire",10,13
    db "Some say in ice",10,13
    db "From what I've tasted of desire",10,13
    db "I hold with those who favor fire",10,13
    db "But if I had to perish twice,",10,13
    db "I think I know enough of hate",10,13
    db "To say that for destruction ice",10,13
    db "is also great and would suffice."
    db "Robert Frost - Fire and Ice"
    db 0
start:
    xor ax,ax
    mov ds,ax
    mov es,ax
    mov si, str
    xor bx,bx
    mov ah, 0x0e
print:
    lodsb   ;al = current char
    cmp al, 0
    je end
    int 0x10
    jmp print
end:    
    cli
    hlt

    times 510 - ($-$$) db 0
    dw 0xAA55
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Solution

  • Because it starts executing code right at the instruction at 7c00. That, unfortunately is where you have your string.

    You should precede that string with a jmp instruction so that it jumps to start.

    This is usually a short jump EB xx followed by a NOP 90. Some BIOS' may insist on that being of this form even though it doesn't really matter to the processor.

    In other words, you'd be looking for something like:

    org 0x7c00
    bits 16
    realstart:
        jmp short start
        nop
    str:
        db "Some say the world will end in fire",10,13
        :
        db "Robert Frost - Fire and Ice"
        db 0
    start:
        xor  ax,ax
        :
    

    Just keep in mind that the short jump is limited as to what distance it can go, roughly +/-128 bytes, so your string size will be necessarily limited by that. If your BIOS doesn't require the EB xx 90 format, you can just do a regular jump.

    The other thing you could try is to move the entire string to after the hlt instruction:

    org 0x7c00
    bits 16
    start:
        xor  ax,ax
        :
    end:    
        cli
        hlt
    str:
        db "Some say the world will end in fire",10,13
        :
        db "Robert Frost - Fire and Ice"
        db 0
    

    but, again, this depends on your BIOS not requiring the jmp/nop combo at the start.