La fonction de lecture de disque ne fonctionne pas comme prévu dans le chargeur de démarrage
J'essaie de développer un chargeur de démarrage de base, mais j'ai rencontré un problème lorsque j'ai essayé de créer une fonction pour lire des secteurs supplémentaires à partir d'un disque dur. Je le développe sur Kali Linux dans NASM et j'utilise QEMU comme émulateur. Ceci est mon fichier de bootloader principal:
[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
Comme vous pouvez le voir, my_string
se trouve après 512 octets, dans le deuxième secteur du disque dur émulé. Mais lorsque je compile et exécute le chargeur de démarrage, il ne produit rien. Dans le code que j'ai fourni ci-dessus, j'imprime une my_string
fois la read_disk
fonction terminée. Mais curieusement, si je déplace les deux lignes qui s'impriment my_string
à l' intérieur de la fonction, cela fonctionne. C'est le code qui fonctionne:
[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
Je serais très reconnaissant si quelqu'un pouvait m'expliquer cette étrange bizarrerie.
Réponses
Vous devez définir SS: SP et pas seulement comme SP avant de lire en mémoire. SS peut être égal à zéro ou non. Si SS se trouve être 0x0000, votre pile est à 0x0000: 0x8000 et elle augmentera à partir de là.
Votre code lit le deuxième secteur de 512 octets sur le disque en mémoire à 0x0000: 0x7e00 qui comprend tous les octets jusqu'à et y compris l'adresse de retour de la disk_read
fonction qui a été placée sur la pile à 0x0000: 0x7ffe à 0x0000: 0x7fff.
Depuis que vous avez écrasé la pile, le int 0x13
ne reviendra probablement jamais car les données internes, l'adresse de retour et les indicateurs ont été corrompus. Une telle corruption de la pile aura des résultats imprévisibles. Pensez à placer la pile à 0x0000: 0x7c00 sous le chargeur de démarrage afin de ne pas interférer avec les données et le code que vous chargez après le chargeur de démarrage.
Remarque: vous devez définir tous les registres de segments dont vous avez besoin sur les valeurs attendues. Vous ne devez vous fier à aucun des registres de segments contenant une valeur spécifique. Le BIOS ne garantit pas leurs valeurs, bien que dans la plupart des émulateurs, elles soient 0x0000.