Почему этот код загрузчика не работает?

Я ожидаю, что он печатает строку, но ничего не распечатывается. Когда я укорачиваю строку, это иногда срабатывает, а когда я снова удлиняю их, это иногда срабатывает.

Я не знаю, почему это не работает.

Может ли кто-нибудь помочь мне? Спасибо.

Код сборки, который я использую:

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

person kim taeyun    schedule 18.04.2011    source источник
comment
Я думаю, вам нужно добавить инструкцию CLD, чтобы гарантировать, что lodsb увеличивает si, а не уменьшает его. Однако я думаю, что есть и другая проблема.   -  person Robin Green    schedule 18.04.2011


Ответы (2)


Потому что он начинает выполнение кода прямо с инструкции в 7c00. Это, к сожалению, где у вас есть строка.

Вы должны предварить эту строку инструкцией jmp, чтобы она перешла к start.

Обычно это короткий переход EB xx, за которым следует NOP 90. Некоторые BIOS могут настаивать на этой форме, даже если это не имеет большого значения для процессора.

Другими словами, вы ищете что-то вроде:

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
    :

Просто имейте в виду, что короткий переход ограничен расстоянием, которое он может пройти, примерно +/- 128 байт, поэтому размер вашей строки обязательно будет ограничен этим. Если ваш BIOS не требует формата EB xx 90, вы можете просто сделать обычный переход.

Другая вещь, которую вы можете попробовать, это переместить всю строку после инструкции hlt:

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

но, опять же, это зависит от вашего BIOS, не требующего комбинации jmp/nop в начале.

person paxdiablo    schedule 18.04.2011
comment
благодаря. но я все еще удивляюсь. не могли бы вы решить мой вопрос = почему иногда работает, даже если строка находится прямо на 0x7c00? - person kim taeyun; 18.04.2011
comment
возможно, некоторые строки могут быть интерпретированы как действительный код, который в конечном итоге приводит к выполнению реального кода. - person Igor Skochinsky; 18.04.2011

Хороший способ проверить правильность paxdiablo и Игоря Скочинского — поместить текстовую строку в файл, а затем прогнать ее через дизассемблер. Короткие строки, которые печатаются правильно, должны дизассемблироваться в строку кода, которая ничему не повредит. Более короткие строки, в которых произошел сбой, и более длинные строки будут либо содержать недопустимые инструкции, инструкции перехода или вызова, либо даже просто иметь 2- или 3-байтовую инструкцию в конце, которая съедает код операции для инструкции "xor ax,ax" в начале вашего кода. код.

person cmarslett    schedule 16.05.2011