Fungsi Pembacaan Disk tidak Berfungsi seperti yang Diharapkan di Bootloader

Aug 16 2020

Saya mencoba mengembangkan bootloader dasar, tetapi saya mengalami masalah saat mencoba membuat fungsi untuk membaca sektor tambahan dari hard drive. Saya mengembangkannya di Kali Linux di NASM dan menggunakan QEMU sebagai emulator saya. Ini adalah file bootloader utama saya:

[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

Seperti yang Anda lihat, my_stringterletak setelah 512 byte, di sektor kedua dari hard drive yang diemulasi. Tetapi ketika saya mengkompilasi dan menjalankan bootloader, itu tidak menghasilkan apa pun. Dalam kode yang saya berikan di atas, saya mencetak my_string setelah itu read_diskfungsi berakhir. Tapi anehnya, Jika saya memindahkan dua baris yang mencetak my_string di dalam fungsi, itu berhasil. Ini adalah kode yang berfungsi:

[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

Saya akan sangat berterima kasih jika seseorang dapat menjelaskan keanehan aneh ini kepada saya.

Jawaban

4 MichaelPetch Aug 16 2020 at 14:38

Anda harus mengatur SS: SP dan tidak hanya sebagai SP sebelum membaca ke dalam memori. SS mungkin nol atau mungkin juga tidak. Jika SS kebetulan 0x0000 maka tumpukan Anda di 0x0000: 0x8000 dan itu akan tumbuh dari sana.

Kode Anda membaca sektor 512 byte kedua pada disk ke memori pada 0x0000: 0x7e00 yang mencakup semua byte hingga dan termasuk alamat kembalian dari disk_readfungsi yang ditempatkan pada tumpukan pada 0x0000: 0x7ffe hingga 0x0000: 0x7fff.

Karena Anda memanjat tumpukan, int 0x13kemungkinan besar tidak akan pernah kembali karena data internal, alamat pengirim, dan benderanya telah rusak. Merusak tumpukan seperti ini akan memiliki hasil yang tidak dapat diprediksi. Pertimbangkan untuk meletakkan tumpukan pada 0x0000: 0x7c00 di bawah bootloader agar tidak mengganggu data dan kode yang Anda muat setelah bootloader.

Catatan: Anda harus menyetel semua register segmen yang Anda perlukan ke nilai yang Anda harapkan. Anda tidak boleh mengandalkan register segmen mana pun yang berisi nilai tertentu. BIOS tidak menjamin nilainya, meskipun di kebanyakan emulator nilainya 0x0000.