부트 로더에서 디스크 읽기 기능이 예상대로 작동하지 않음

Aug 16 2020

기본 부트 로더를 개발하려고하는데 하드 드라이브에서 추가 섹터를 읽는 기능을 만들려고 할 때 문제가 발생했습니다. 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

누군가가이 이상한 기이함을 나에게 설명해 주시면 매우 감사하겠습니다.

답변

4 MichaelPetch Aug 16 2020 at 14:38

메모리로 읽기 전에 SP 뿐만 아니라 SS : SP를 설정해야 합니다. SS 는 0이거나 그렇지 않을 수 있습니다. 경우 SS는 0000 될 일이 다음 스택은 0000에 있습니다 : 0x8000을하고 거기에서 아래로 성장할 것입니다.

코드는 0x0000 : 0x7ffe에서 0x0000 : 0x7fff까지 disk_read스택에 배치 된 함수 의 반환 주소를 포함하여 모든 바이트를 포함하는 0x0000 : 0x7e00의 메모리로 디스크의 두 번째 512 바이트 섹터를 읽습니다 .

스택을 제거 int 0x13했으므로 내부 데이터, 반환 주소 및 플래그가 손상 되었기 때문에는 반환되지 않을 것입니다. 이와 같이 스택을 손상 시키면 예측할 수없는 결과가 발생합니다. 부트 로더 이후에로드하는 데이터 및 코드를 방해하지 않도록 스택을 부트 로더 아래 0x0000 : 0x7c00에 배치하는 것을 고려하십시오.

참고 : 필요한 모든 세그먼트 레지스터를 원하는 값으로 설정해야합니다. 특정 값을 포함하는 세그먼트 레지스터에 의존해서는 안됩니다. BIOS는 값을 보장하지 않지만 대부분의 에뮬레이터에서는 0x0000입니다.