J'essaie de charger le numéro de secteur de [head = 0, cilinder (track) = 1, sector = 1] à partir de disquette en utilisant l'interruption du BIOS 13h, depuis mon chargeur de démarrage fat12. J'utilise le sous-programme read_sectors pour lire le secteur et le charger à es: bx.Le BIOS int 13h ne peut pas lire la première piste
Ce code fonctionne bien avec n'importe quel secteur de la première piste, mais il lit juste 0s de n'importe quel secteur des autres pistes, alors que ces secteurs sont réellement peuplés. Avec le secteur 18, par exemple, cx est 0x0041, ce qui est juste. Le problème est, l'interruption définit CF, en disant qu'il y a une erreur. Il définit également ah (code de retour) à 1, et al (secteurs lire) à 1.
Ceci est le fichier complet bootloader .asm
bits 16
org 0
start: jmp load
nop
OEM: DB "ptiaOS "
bytesPerSector: DW 512
sectorsPerCluster: DB 1
reservedSectors: DW 1
numberOfFATs: DB 2
rootEntries: DW 224
totalSectors: DW 2880
media: DB 0xf8
sectorsPerFAT: DW 9
sectorsPerTrack: DW 18
headsPerCylinder: DW 2
hiddenSectors: DD 0
totalSectorsBig: DD 0
driveNumber: DB 0
unused: DB 0
extBootSignature: DB 0x29
serialNumber: DD 0xa0a1a2a3
volumeLabel: DB "PTIAOS FLP "
fileSystem: DB "FAT12 "
load:
;The bootloader is loaded at the address 0x7C00 and is 0x200 (512) bytes long
cli
mov ax, 0x07C0 ; setup registers to point to our segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
sti
mov si, hello_string
call prints
mov si, try_string
call prints
mov ax, 18
call lba_to_chs
mov al, 2
mov bx, 0x200
call read_sectors
mov si, success_string
call prints
mov si, 0x200
call prints
cli
hlt ;halt
;--------DATA--------
hello_string db `Hi, bootloader of ptiaOS here\n\r`, 0
success_string db `Successfully loaded from floppy\n\r`, 0
try_string db `Loading more data from floppy...\n\r`, 0
;CHS position of the sector to read
sector_number db 0 ;1 is the first (they're 18 per track)
cilinder_number db 0 ;track number: 0 is the first (they're 80 per side)
head_number db 0 ;0 is the first (the're 2)
;---SOTTOPROGRAMMI---
;print a 0-terminated string pointed by ds:si
prints:
mov ah, 0x0E ;dico all'interrupt del BIOS video di eseguire la funzione di stampa [al: carattere, bh: pagina]
.prints_printchar:
lodsb ;al = *(si++)
cmp al, 0
je .prints_end ;if(al == 0) goto print_string_end
int 0x10 ;chiamo l'interrupt di i/o dello schermo, con ah = 0x0E per stampare il carattere in al
jmp .prints_printchar
.prints_end:
ret
;Read sectors from floppy at the address specified by CHS variables, and load them in es:bx
read_sectors:
mov ah, 0x02 ;function 0x02, interrupt 0x13: read sectors
;al (the number of sectors to read), es:bx (destination) are set as arguments
xor cx, cx
mov cl, [cylinder_number]
shl cl, 6
or cl, [sector_number]
mov dh, [head_number]
mov dl, 0
int 0x13
jnc .sectors_read_successfully ;CF = 0 if no errors, 1 otherwise
;if errors occured, try to reset floppy
.flp_reset:
mov ah, 0 ;function 0, interrupt 0x13: reset disk
mov dl, 0 ;disk to reset: 0=floppy
int 0x13
jc .flp_reset ;CF = 0 if no errors, 1 otherwise
jmp read_sectors
.sectors_read_successfully:
ret
lba_to_chs:
mov cx, ax
mov bl, [sectorsPerTrack]
div bl
inc ah ;ah = lba % 18 + 1
mov byte [sector_number], ah
mov ax, cx
mov bl, [sectorsPerTrack]
div bl ;al = lba/18
cbw ;ax = lba/18
mov bl, [headsPerCylinder]
div bl ;al = lba/18/2; ah = lba/18 % 2
mov byte [cilinder_number], ah
mov byte [head_number], al
ret
times 510-($-$$) db 0
dw 0xAA55
Je courais ce code sur qemu, à partir d'Ubuntu, et la compiler avec
nasm -f bin -o ptiaos.bin ptiaboot.asm
nasm -f bin -o BSTAGE2.SYS blstage2.asm
mkdir floppy
dd status=noxfer conv=notrunc if=ptiaos.bin of=ptiaos.flp
sudo mount -o loop ptiaos.flp floppy
sudo cp BSTAGE2.SYS floppy
sleep 0.1
sudo umount floppy
rm BSTAGE2.SYS
rm ptiaos.bin
rmdir floppy
Vous devez calculer l'adresse correcte de CHS pour la géométrie l'appareil que vous lisez que je ne vois pas dans votre code. Ce n'est pas trivial. J'ai trouvé [cette page OSdev] (http://wiki.osdev.org/ATA_in_x86_RealMode_%28BIOS%29) utile pour [mon implémentation] (https://github.com/neonics/qure/blob/master/bootloader/sector1 .s # L1679). – Kenney
En fait, j'utilise un sous-programme basé sur la page OSdev pour calculer l'adresse CHS. Je l'ai juste omis de la question, car il semble fonctionner correctement, et a passé l'adresse chs directement à la fonction read_sectors. L'adresse [head = 0, cilinder (track) = 1, sector = 1] est en fait l'adresse LBA (indexée 0) 18. Si vous pensez que j'ai besoin d'afficher la sous-routine ici, je l'afficherai. Merci d'avoir répondu si rapidement. – ptia
De rien. Je vérifiais simplement - d'après mon expérience, le problème réside généralement dans le calcul du CHS, ou dans l'hypothèse d'un mauvais nombre de cylindres/têtes/pistes pour le lecteur. Vous avez donc des difficultés à lire l'adresse LBA 19 et suivantes: avez-vous vérifié manuellement que le LBA 19 est converti au bon CHS? Si c'est le cas, il n'est pas nécessaire d'afficher le calcul CHS. Encore une chose: les données sont lues dans 'es: bx' et je ne vois pas comment' bx' est initialisé. – Kenney