부트 로더에서 디스크 읽기 기능이 예상대로 작동하지 않음
기본 부트 로더를 개발하려고하는데 하드 드라이브에서 추가 섹터를 읽는 기능을 만들려고 할 때 문제가 발생했습니다. NASM의 Kali Linux에서 개발하고 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_string
, 에뮬레이트 된 하드 드라이브의 두 번째 섹터에서 512 바이트 뒤에 있습니다. 그러나 부트 로더를 컴파일하고 실행하면 아무것도 출력되지 않습니다. 위에서 제공 한 코드 에서 함수가 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
누군가가이 이상한 기이함을 나에게 설명해 주시면 매우 감사하겠습니다.
답변
메모리로 읽기 전에 SP 뿐만 아니라 SS : SP를 설정해야 합니다. SS 는 0이거나 그렇지 않을 수 있습니다. 경우 SS는 0000 될 일이 다음 스택은 0000에 있습니다 : 0x8000을하고 거기에서 아래로 성장할 것입니다.
코드는 0x0000 : 0x7ffe에서 0x0000 : 0x7fff까지 disk_read
스택에 배치 된 함수 의 반환 주소를 포함하여 모든 바이트를 포함하는 0x0000 : 0x7e00의 메모리로 디스크의 두 번째 512 바이트 섹터를 읽습니다 .
스택을 제거 int 0x13
했으므로 내부 데이터, 반환 주소 및 플래그가 손상 되었기 때문에는 반환되지 않을 것입니다. 이와 같이 스택을 손상 시키면 예측할 수없는 결과가 발생합니다. 부트 로더 이후에로드하는 데이터 및 코드를 방해하지 않도록 스택을 부트 로더 아래 0x0000 : 0x7c00에 배치하는 것을 고려하십시오.
참고 : 필요한 모든 세그먼트 레지스터를 원하는 값으로 설정해야합니다. 특정 값을 포함하는 세그먼트 레지스터에 의존해서는 안됩니다. BIOS는 값을 보장하지 않지만 대부분의 에뮬레이터에서는 0x0000입니다.