डिस्क पढ़ें फ़ंक्शन बूटलोडर में अपेक्षित रूप से कार्य नहीं कर रहा है

Aug 16 2020

मैं एक बुनियादी बूटलोडर विकसित करने की कोशिश कर रहा हूं, लेकिन मैं एक समस्या में भाग गया जब मैंने हार्ड ड्राइव से अतिरिक्त क्षेत्रों को पढ़ने के लिए एक फ़ंक्शन बनाने की कोशिश की। मैं इसे NASM में काली लिनक्स पर विकसित कर रहा हूं और QEMU को अपने एमुलेटर के रूप में उपयोग कर रहा हूं। यह मेरी मुख्य बूटलोडर फ़ाइल है:

[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

जैसा कि आप देख सकते हैं, my_string512 बाइट्स के बाद, नकली हार्ड ड्राइव के दूसरे सेक्टर में निहित है। लेकिन जब मैं बूटलोडर को संकलित और चलाता हूं, तो यह कुछ भी आउटपुट नहीं करता है। ऊपर दिए गए कोड में, मैं फ़ंक्शन समाप्त my_string होने के बाद प्रिंट कर रहा हूं read_disk। लेकिन अजीब तरह से, अगर मैं फ़ंक्शन के my_string अंदर प्रिंट करने वाली दो पंक्तियों को स्थानांतरित करता हूं , तो यह काम करता है। यह वह कोड है जो काम करता है:

[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

मैं बहुत आभारी रहूंगा अगर कोई मुझे इस अजीब विषमता की व्याख्या कर सकता है।

जवाब

4 MichaelPetch Aug 16 2020 at 14:38

आपको मेमोरी में पढ़ने से पहले एसएस: एसपी और न केवल एसपी के रूप में सेट करना चाहिए । एसएस शून्य हो सकता है या यह नहीं हो सकता है। यदि SS 0x0000 होता है तो आपका स्टैक 0x0000: 0x8000 पर होता है और यह वहाँ से नीचे बढ़ेगा।

आपका कोड डिस्क पर मेमोरी के लिए दूसरे 512 बाइट सेक्टर को 0x0000: 0x7e00 पर पढ़ता है जिसमें disk_readफ़ंक्शन के रिटर्न एड्रेस सहित सभी बाइट्स शामिल हैं जो 0x0000: 0x7ffe से 0x0000: 0x7fff पर स्टैक पर रखा गया था।

चूंकि आपने स्टैक को बंद कर दिया था, int 0x13इसलिए संभवतः वापस नहीं आएगा क्योंकि आंतरिक डेटा, रिटर्न एड्रेस और झंडे भ्रष्ट हो गए हैं। इस तरह से स्टैक को दूषित करने के अप्रत्याशित परिणाम होंगे। बूटलोडर के नीचे 0x0000: 0x7c00 पर स्टैक लगाने पर विचार करें ताकि बूट लोडर के बाद आपके द्वारा लोड किए गए डेटा और कोड के साथ हस्तक्षेप न करें।

नोट: आपको उन सभी सेगमेंट रजिस्टरों को सेट करना चाहिए जिनकी आपको उन मूल्यों की आवश्यकता है जो आप अपेक्षा करते हैं। आपको किसी विशिष्ट मूल्य वाले सेगमेंट रजिस्टर पर भरोसा नहीं करना चाहिए। BIOS उनके मूल्यों की गारंटी नहीं देता है, हालांकि अधिकांश एमुलेटर में वे 0x0000 होंगे।