qemu의 RAM에 섹터로드

Nov 13 2020

섹터 (섹터 번호 2)를 RAM에로드하는 간단한 프로그램을 코딩합니다.

그러나 아무것도 인쇄하지 않습니다.

먼저 부트 섹터에 대해이 코드를 시도했습니다.

org 0x7c00

mov ax, 0x1000 ; ES:BX = 1000:0000
mov es, ax
mov bx, 0x00

LoadSectortoMemory:
mov al, 0x01 ; Load 1 sectors
mov ah, 0x02 ; Load disk data to ES:BX
mov cl, 0x02 ; Sector = 2
mov ch, 0x00 ; Cylinder = 0
mov dl, 0x00 ; Drive = 0
mov dh, 0x00 ; Head = 0
int 13h ; Read
jc LoadSectortoMemory ; ERROR => Try again

jmp 0x1000:0x0000

times 510-($-$$) db 0
dw 0xaa55

사용자로부터 사용자 이름과 비밀번호를 가져 와서 프로그램을 종료하는 커널 :

mov si,Username

call Write
call Read
call Next_Line
call Pass
call Read
call Next_Line
call Kernel_Exit

Write:
mov al,[si]
mov ah,0x0e
mov bl,0x07
mov bh,0x00
int 0x10
inc si
mov dl,[si]
cmp dl,0x00
jne Write
ret

Read:
mov ah,0x00
int 0x16
mov ah,0x0e
mov bl,0x07
mov bh,0x00
int 0x10
cmp al,0x0d
jne Read
ret

Pass:
mov si,Password
call Write
ret

Next_Line:
mov al,0x0a
mov ah,0x0e
mov bl,0x07
mov bh,0x00
int 0x10
ret

Kernel_Exit:
mov si,Done
call Write
mov ah,0x4c
int 0x21

Username db 'Username: ',0
Password db 'Password: ',0
Done db 'Done',0

times 510-($-$$) db 0

그리고 작동하지 않았다

검색 후이 코드를 시도했습니다 (마지막에 추가 된 레지스터 : /).

bits 16
org 0x7c00

mov ax, 0x1000 ; ES:BX = 1000:0000
mov es, ax
mov bx, 0x00

LoadSectortoMemory:
mov al, 0x01 ; Load 1 sectors
mov ah, 0x02 ; Load disk data to ES:BX
mov cl, 0x02 ; Sector = 2
mov ch, 0x00 ; Cylinder = 0
mov dl, 0x00 ; Drive = 0
mov dh, 0x00 ; Head = 0
int 0x13 ; Read!
jc LoadSectortoMemory ; ERROR => Try again

mov ax, 0x1000
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax

jmp 0x1000:0x0

times 510-($-$$) db 0
dw 0xaa55

다시 작동하지 않았다

내가 사용하는 명령 줄 :

nasm -fbin BootSector.asm -o Bootsector.bin

nasm -fbin Kernel.asm -o Kernel.bin

cat BootSector.bin Kernel.bin > Code.bin

qemu-system-x86_64 Code.bin

qemu에 문제가 있습니까?

누구든지 내 문제로 나를 도울 수 있습니까?

미리 감사드립니다

답변

3 ecm Nov 13 2020 at 18:08

코드에 몇 가지 문제가 있습니다. 첫째, 가장 중요한 것 :

LoadSectortoMemory:
mov al, 0x01 ; Load 1 sectors
mov ah, 0x02 ; Load disk data to ES:BX
mov cl, 0x02 ; Sector = 2
mov ch, 0x00 ; Cylinder = 0
mov dl, 0x00 ; Drive = 0
mov dh, 0x00 ; Head = 0
int 0x13 ; Read!
jc LoadSectortoMemory ; ERROR => Try again

이것은 드라이브 유닛 0에서 부팅하는 경우에만 작동합니다. 기본적으로 qemu는 이미지를 드라이브 장치 80h (hda = 첫 번째 하드 디스크)로 설정하는 것처럼 보입니다. 장치 0 (fda = 첫 번째 디스켓)에서로드되었다고 가정합니다. 따라서 매개 변수 -fda code.bin를 사용하여 qemu에 파일을 디스켓 이미지 dl로 사용 하도록 지시 하거나 ROM-BIOS가 제어권을 전송하기 전에 ROM-BIOS에서 초기화 한대로로드 할 단위를 사용하도록 수정하는 줄을 삭제 해야합니다. 당신의 로더.


이미 로더를 수정하여 세그먼트 레지스터를 설정했습니다. 특히 ds커널이 해당 세그먼트 레지스터를 (암시 적으로) 사용하여 메시지에 액세스하기 때문에 1000h로 설정해야합니다. (kernel.asm에는 org행이 없으므로 NASM은 org 0여기 의 기본값을 사용 합니다.) ds부트 로더에서 설정하는 대신 kernel.asm 시작 부분에 다음을 추가 할 수도 있습니다.

push cs
pop ds

ds값으로 설정 됩니다 cs. Real 86 모드에서 이것은 코드 세그먼트와 동일한 기본 주소를 가진 데이터 세그먼트 참조를 가져 오는 데 유효합니다 (그러나 읽기 / 쓰기 권한이 있음).


설정 외에도 설정 ss해야합니다 sp. 당신은 설정해야합니다 sp세트 그 하나 바로 다음 명령에 ss. 예:

mov ax, 1000h
cli
mov ss, ax
xor sp, sp
sti

이것은 sp0으로 설정 됩니다. 언더 플로 때문에 처음 사용 된 스택 슬롯은 ss:0FFFEh(전체 64KiB 세그먼트의 상단)에 있습니다.


에서 Kernel_Exit당신이 21H 서비스 4 채널 인터럽트를 사용하고 있습니다. 이 서비스는이 환경에서 사용할 수 없습니다. 다음과 같은 다른 것을 사용해야합니다.

xor ax, ax
int 16h ; wait for key pressed
int 19h ; reboot

아니면 이거:

sti
halt:
hlt ; wait for external interrupt, keep CPU usage low
jmp halt ; jump infinitely to stop program flow

에서 Next_Line이 있습니다 :

Next_Line:
mov al,0x0a
mov ah,0x0e
mov bl,0x07
mov bh,0x00
int 0x10
ret

이것은 종료 13 (CR = 캐리지 리턴)을 표시 할 때 끝나는 Next_Line이전에 사용한 Read때 마다 작동하기 때문에 발생합니다 . Next_Line보다 일반적으로, 먼저 13 (CR)을 표시 한 다음 10 (LF = Line Feed)을 표시해야합니다. 즉, 다음을 수행해야합니다.

Next_Line:
mov al, 13
mov ah,0x0e
mov bl,0x07
mov bh,0x00
int 0x10
mov al, 10
int 10h
ret

kernel.asm의 끝에 있는 줄 을 사용하고 있습니다. 대신 사용 하여 최대 510 바이트가 아닌 전체 섹터를 채워야합니다.times 510-($-$$) db 0times 512 - ($ - $$) db 0