Ваш код предполагает, что DS установлен в 0. Вы не можете этого принять. Первая часть вашего кода должна явно установить DS на 0, если вы используете org 0x7c00
.
Вы должны серьезно подумать над определением своего стека, установив SS: SP. Вы не знаете, где находится существующий, или он достаточно велик, чтобы обрабатывать то, что вы намереваетесь сделать.
Перед загрузкой вашего загрузчика BIOS установит регистратор DL с номером загрузочного устройства. Вы не должны устанавливать DL на 0 в коде при выполнении запросов на диске с загрузочного диска. Вы должны использовать значение, которое существовало в DL, когда был вызван ваш загрузчик.
Вы должны использовать CLD команду очистить флаг направления, так как вы используете LODSB инструкции, ожидая двигаться вперед в памяти. Нет гарантии, что флаг направления будет правильно установлен, поэтому вы должны явно указать его в нужное вам направление с CLD (вперед) или STD (назад).
У меня есть дополнительная информация по вышеуказанным вопросам в моем ответе StackOverflow с помощью General Bootloader Tips.
Поскольку вы не используете BPB, я настоятельно рекомендую удалить jmp start
в качестве первой инструкции вашего загрузчика. Вместо этого перемещайте данные после кода, но перед сигнатурой загрузочного сектора (0xAA55
). Причиной этого является то, что некоторые BIOS попытаются найти BPB на основе инструкции JMP, которая появляется в качестве первой инструкции загрузчика и, если она найдена, перезаписывает части вашего загрузчика в памяти, вызывая потенциально неопределенное поведение.
Ваш Загрузчик использует эту инструкцию, чтобы начать свой второй этап загружается из второго сектора:
jmp 0x0:0x1000
Проблема заключается в том, что, когда вы читаете сектор настройки ES: BX этот путь:
read_sector:
mov ax, 0x0
mov es, ax
xor bx, bx
Это устанавливает ES: BX до 0x0000: 0x0000, который явно не там, где находится ваш JMP ожидает код. Вам необходимо установить ES: BX в ячейку памяти, которую вы хотите INT 13/AH=02h, чтобы прочитать сектор (сектора) диска.
INT 13h/AH = 02h требует, чтобы номер цилиндра/головки/сектора был установлен правильно. Секторы начинают нумерацию на 1, но Цилиндры и Головки основаны на нуле. Второй сектор диска на цилиндре 0, головка 0, сектор 2. Ваш код устанавливает цилиндр 1 вместо 0. Этот код является ошибочным, так как вы действительно должны установить его в 0:
mov ch, 01
в вашем второй этап, который вы создали print
как функция, так как он заканчивается инструкцией RET
. jmp print
следует изменить на call print
.
При всех изменениях, рекомендованных выше, в том числе из моих общих советов загрузчике ваш код может быть изменен, чтобы быть:
boot.asm
[bits 16]
[org 0x7c00]
; Use the boot drive number passed to us by BIOS in register DL
start:
xor ax,ax ; We want a segment of 0 for DS for this question
mov ds,ax ; Set AX to appropriate segment value for your situation
mov es,ax ; In this case we'll default to ES=DS
mov bx,0x8000 ; Stack segment can be any usable memory
mov ss,bx ; This places it with the top of the stack @ 0x80000.
mov sp,ax ; Set SP=0 so the bottom of stack will be @ 0x8FFFF
cld ; Set the direction flag to be positive direction
mov si, wolf_wel_msg
call wolf_print
mov si, wolf_kernel_load
call wolf_print
pushf
stc
mov ah,00
int 13h
read_sector:
mov ax, 0x0
mov es, ax ; ES = 0
mov bx, 0x1000 ; BX = 0x1000. ES:BX=0x0:0x1000
; ES:BX = starting address to read sector(s) into
mov ah, 02 ; Int 13h/AH=2 = Read Sectors From Drive
mov al, 01 ; Sectors to read = 1
mov ch, 00 ; CH=Cylinder. Second sector of disk
; is at Cylinder 0 not 1
mov cl, 02 ; Sector to read = 2
mov dh, 00 ; Head to read = 0
; DL hasn't been destroyed by our bootloader code and still
; contains boot drive # passed to our bootloader by the BIOS
int 13h
jc wolf_error
popf
jmp 0x0:0x1000
cli
hlt
wolf_error:
mov si, wolf_error_msg
call wolf_print
mov si, wolf_error_msg1
call wolf_print
mov ah,00
int 16h
xor ax,ax
int 19h
wolf_print:
lodsb
or al,al
jz exit
mov ah,0x0e
int 10h
jmp wolf_print
exit:
ret
; Moved the data before the boot signature but after the code
wolf_wel_msg db 'Welcome to Bootloader!!!',0x0D,0x0A,0
wolf_kernel_load db 'Loading kernel....',0x0D,0x0A,0
wolf_error_msg db 'Kernel.bin not found!',0x0D,0x0A,0
wolf_error_msg1 db 'Press any key to restart..',0
times 510-($-$$) db 0
dw 0xAA55
hello.asm
[org 0x1000]
jmp start
data:
msg db 'Hello',0
start:
mov si, msg
call print ; print is a function, use CALL instead of JMP
cli
hlt
print:
lodsb
or al, al
jz exit
mov ah,0x0e
int 10h
jmp print
exit:
ret
Поскольку, как представляется, вы используете Windows на основе информации, указанной в вашей команде DD, у вас может возникнуть другая проблема. Я не знаю, какой DD вы используете, но of=\\.\d:
не записывает в начало диска (USB-накопитель), он будет записывать в раздел, в котором находится D:, а не в начале самого диска.
Я рекомендую использовать последние DD от Chrysocome. На сегодняшний день последнее - 0.6beta3. Я рекомендую эту версию, потому что она позволяет вам правильно обращаться к диску (или USB-накопителю) относительно начала диска, а не по отношению к началу определенного раздела. Это может привести к серьезным проблемам, требующим правильного хранения 1-го и 2-го секторов. В последней версии я хотел бы использовать эти команды с правами администратора записать на диск USB:
dd if=f:\boot.bin od=d: bs=512 count=1
dd if=f:\hello.bin od=d: bs=512 seek=1 count=1
Это предполагает, что ваша USB диск находится на диске D: как это предлагается в вашем вопросе. ВНИМАНИЕ: Неправильное использование диска может привести к потере данных и повреждению на другом устройстве!
Если эти команды работают должным образом, на выходе должно выглядеть примерно так:
dd if=boot.bin od=d: bs=512 count=1
rawwrite dd for windows version 0.6beta3.
Written by John Newbigin <[email protected]>
This program is covered by terms of the GPL Version 2.
Device d: is a link to \\?\Device\HarddiskVolume5 \\?\Device\HarddiskVolume5 is a partition on \Device\Harddisk1
512 100%
1+0 records in
1+0 records out
dd if=hello.bin od=d: bs=512 seek=1 count=1
rawwrite dd for windows version 0.6beta3.
Written by John Newbigin <[email protected]>
This program is covered by terms of the GPL Version 2.
Device d: is a link to \\?\Device\HarddiskVolume5 \\?\Device\HarddiskVolume5 is a partition on \Device\Harddisk1
28 5%
0+1 records in
0+1 records out
После того, как вы оформили эти команды, Windows может автоматически обнаружить, что диск больше не отформатирован. Не разрешайте Windows форматировать диск. Если вы разрешите форматировать диск, он переразметит его и отформатирует. При этом он уничтожит загрузочный сектор, который вы написали. При появлении запроса просто отмените диалоговое окно , которое может отображаться.
Не забудьте правильно демонтировать/извлечь USB-накопитель, прежде чем удалять его из системы. Неправильное размонтирование приведет к тому, что данные не будут правильно/полностью записаны на диск.
Если вы хотите создать образ диска для Bochs, QEMU, DOSbox и т.д. Вы можете создать 720K дискету с этими командами в командной строке:
dd if=/dev/zero of=disk.img bs=1024 count=720
dd if=f:\boot.bin of=disk.img bs=512 count=1 conv=notrunc
dd if=f:\hello.bin of=disk.img bs=512 seek=1 count=1 conv=notrunc
Изображение файла disk.img
должны быть доступны Bochs, QEMU , DOSbox и т. Д. Или записаны на дискету 720k для использования на реальном компьютере.
/dev/zero
выглядит как типичное устройство Unix/Linux. Команда DD для Windows. Я предложил использовать в качестве специального устройства ввода значения /dev/zero
, которые генерируют нули. Windows не имеет /dev/zero
устройства, но DD видит это как специальное внутреннее устройство и имитирует его.
При запуске с Bochs 2.6.8 на MS Windows это то, что я видел:
![enter image description here](https://i.stack.imgur.com/EkHZs.png)
На моем Lenovo L520 ноутбуков (не EFI BIOS) с карты памяти USB 16GB это что я видел:
![enter image description here](https://i.stack.imgur.com/EF485.jpg)
Что вы уже пробовали? Что именно «не работает»? Вы вообще ничего не получаете? – Yexo
Нет. Я получаю вывод, говорящий «kernel.bin not found». Это означает, что перенос установлен (Неудачный). –
«hello.bin» не загружен из второго сектора. –