2016-03-16 5 views
5

Я изучаю язык ассемблера. Я написал простой загрузчик. После тестирования это не сработало. Вот мой код:Включите загрузчик для загрузки второго сектора USB

[bits 16] 
[org 0x7c00] 

jmp start 

data: 
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 

start: 
     mov si, wolf_wel_msg 
    call wolf_print 

    mov si, wolf_kernel_load 
    call wolf_print 

    pushf 
    stc 

    mov ah,00 
    mov dl,00 
    int 13h 

    read_sector: 
      mov ax, 0x0 
     mov es, ax 
     xor bx, bx 
      mov ah, 02 
     mov al, 01 
     mov ch, 01 
     mov cl, 02 
     mov dh, 00 
     mov dl, 00 
     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 

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

Этот код находится в первом секторе USB с помощью этой команды:

dd if=f:\boot.bin of=\\.\d: bs=512 count=1 

Простая программа загружается во втором секторе USB, используя эту команду:

dd if=f:\hello.bin of=\\.\d: bs=512 seek=1 count=1 

Это код программы, загруженной во второй сектор:

[bits 16] 
[org 0x1000] 

jmp start 
data: 
    msg db 'Hello',0 
start: 
    mov si, msg 
    jmp print 

    cli 
    hlt 
    print: 
     lodsb 
     or al, al 
     jz exit 
     mov ah,0x0e 
     int 10h 
     jmp print 
    exit: 
     ret 

Почему мой загрузчик не работает? Я сделал что-то не так? Какие-либо предложения?

+0

Что вы уже пробовали? Что именно «не работает»? Вы вообще ничего не получаете? – Yexo

+0

Нет. Я получаю вывод, говорящий «kernel.bin not found». Это означает, что перенос установлен (Неудачный). –

+0

«hello.bin» не загружен из второго сектора. –

ответ

10

Ваш код предполагает, что 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

На моем Lenovo L520 ноутбуков (не EFI BIOS) с карты памяти USB 16GB это что я видел:

enter image description here