La funzione di lettura del disco non funziona come previsto nel Bootloader

Aug 16 2020

Sto cercando di sviluppare un bootloader di base, ma ho riscontrato un problema quando ho provato a creare una funzione per leggere settori aggiuntivi da un disco rigido. Lo sto sviluppando su Kali Linux in NASM e utilizzo QEMU come emulatore. Questo è il mio file bootloader principale:

[org 0x7c00]

mov bp, 0x8000
mov sp, bp

call read_disk

mov si, my_string
call print          ;prints a string, si points to the string to be printed

jmp $ read_disk mov ah, 0x02 ;read from disk mov al, 0x01 ;read one sector mov ch, 0x00 ;read from cylinder 0 mov dh, 0x00 ;read from head 0 mov cl, 0x02 ;read the second sector mov bx, 0 mov es, bx mov bx, 0x7c00+512 int 0x13 jc disk_error ;BIOS sets the carry flag if disk read was unsuccessful ret disk_error: mov si, error_msg call print jmp $
;
;Functions
;
%include "functions/print.asm"
%include "functions/print_hex.asm"
%include "functions/print_nl.asm"
%include "functions/calc_len.asm"
%include "functions/find_string.asm"

;
;Data
;
error_msg:
    db 'Error reading disk', 0

times 510-($-$$) db 0    ;pad out the rest of the bootloader with zeros to increase the size to 512 bytes
dw 0xaa55                ;Magic bytes so BIOS recognizes the hard drive as bootable

;
;SECOND SECTOR
;

my_string:
    db 'Disk read successful', 0

times 512 db 0   ;need to pad out the rest of the sector with zeros since  QEMU requires it

Come puoi vedere, si my_stringtrova dopo 512 byte, nel secondo settore del disco rigido emulato. Ma quando compilo ed eseguo il bootloader, non restituisce nulla. Nel codice che ho fornito sopra, sto stampando my_string dopo che la read_diskfunzione è finita. Ma stranamente, se sposto le due righe che stampano my_string all'interno della funzione, funziona. Questo è il codice che funziona:

[org 0x7c00]

mov bp, 0x8000
mov sp, bp

call read_disk

jmp $ read_disk mov ah, 0x02 ;read from disk mov al, 0x01 ;read one sector mov ch, 0x00 ;read from cylinder 0 mov dh, 0x00 ;read from head 0 mov cl, 0x02 ;read the second sector mov bx, 0 mov es, bx mov bx, 0x7c00+512 int 0x13 jc disk_error ;BIOS sets the carry flag if disk read was unsuccessful mov si, my_string call print ;prints a string, si points to the string to be printed ret disk_error: mov si, error_msg call print jmp $
;
;Functions
;
%include "functions/print.asm"
%include "functions/print_hex.asm"
%include "functions/print_nl.asm"
%include "functions/calc_len.asm"
%include "functions/find_string.asm"

;
;Data
;
error_msg:
    db 'Error reading disk', 0

times 510-($-$$) db 0    ;pad out the rest of the bootloader with zeros to increase the size to 512 bytes
dw 0xaa55                ;Magic bytes so BIOS recognizes the hard drive as bootable

;
;SECOND SECTOR
;

my_string:
    db 'Disk read successful', 0

times 512 db 0   ;need to pad out the rest of the sector with zeros since  QEMU requires it

Sarei molto grato se qualcuno potesse spiegarmi questa strana stranezza.

Risposte

4 MichaelPetch Aug 16 2020 at 14:38

È necessario impostare SS: SP e non solo come SP prima di leggere in memoria. SS potrebbe essere zero o potrebbe non esserlo. Se SS è 0x0000, il tuo stack è 0x0000: 0x8000 e da lì crescerà.

Il codice legge il secondo settore di 512 byte sul disco in memoria a 0x0000: 0x7e00 che include tutti i byte fino ae incluso l'indirizzo di ritorno della disk_readfunzione che è stata inserita nello stack a 0x0000: da 0x7ffe a 0x0000: 0x7fff.

Poiché hai distrutto lo stack, int 0x13probabilmente non tornerà mai perché i dati interni, l'indirizzo di ritorno e i flag sono stati danneggiati. La corruzione dello stack in questo modo avrà risultati imprevedibili. Considera l'idea di mettere lo stack a 0x0000: 0x7c00 sotto il bootloader in modo da non interferire con i dati e il codice che carichi dopo il bootloader.

Nota: è necessario impostare tutti i registri di segmento necessari sui valori previsti. Non dovresti fare affidamento su nessuno dei registri di segmento contenente un valore specifico. Il BIOS non garantisce i loro valori, sebbene nella maggior parte degli emulatori saranno 0x0000.