La funzione di lettura del disco non funziona come previsto nel Bootloader
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_string
trova 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_disk
funzione è 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
È 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_read
funzione che è stata inserita nello stack a 0x0000: da 0x7ffe a 0x0000: 0x7fff.
Poiché hai distrutto lo stack, int 0x13
probabilmente 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.