Why doesn't this boot loader code work?

2019-01-27 03:01发布

问题:

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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

回答1:

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.



回答2:

A good way to verify that paxdiablo and Igor Skochinsky are correct is to put the text string in a file, then run it thorough a disassembler. The shorter strings that print properly should disassemble into a code string that doesn't hurt anything. The shorter strings that fail, and the longer string will either include illegal instructions, jump or call instructions, or even just have a 2- or 3-byte instruction at the end that eats up the opcode for the "xor ax,ax" instruction at the beginning of your code.