Load Sectors to RAM in qemu

和自甴很熟 提交于 2021-01-02 12:50:21

问题



I code a simple program which loads the sector (sector num.2) to the RAM

but prints nothing.

first, I tried this code for bootsector:

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

the kernel which takes the username and password from user then terminate the program:

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

and didn't work

after searching I tried this code (just registers added at the end:/):

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

again didn't work

command lines which I use:

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

is it a problem with qemu?

can anyone help me with my problem?

thanks in advance


回答1:


There are several problems with your code. First, the most important one:

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

This only works if you're being booted from drive unit zero. By default, qemu appears to set up your image as drive unit 80h (hda = first harddisk). You're assuming that you are loaded from unit 0 (fda = first diskette). Therefore, you need to either use the parameters -fda code.bin to tell qemu to use your file as a diskette image, and/or drop the line modifying dl to use the unit-to-load-from as initialised by the ROM-BIOS before it transfers control to your loader.


You already modified your loader to set the segment registers. Especially ds needs to be set to 1000h because your kernel uses that segment register (implicitly) to access its messages. (Your kernel.asm has no org line so NASM uses its default of org 0 here.) Instead of setting ds in the boot loader, you could also add the following to the start of kernel.asm:

push cs
pop ds

This sets ds to the value of cs. In Real 86 Mode, this is valid to get a data segment reference with the same base address as the code segment (but with Read/Write permissions).


Besides setting ss you should also set sp. You should set sp in the immediately following instruction to the one that sets ss. Example:

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

This sets up sp to equal zero. Because of underflow, the first used stack slot will be at ss:0FFFEh (the top of the full 64 KiB segment).


In Kernel_Exit you're using interrupt 21h service 4Ch. This service is not available to you in this environment. You should use something else, such as this:

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

Or this:

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

In Next_Line you have this:

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

This only happens to work because each time you use Next_Line you previously used Read which ends when it displayed a terminating 13 (CR = Carriage Return). Next_Line, to be more general, should display first a 13 (CR) and then a 10 (LF = Line Feed). That is, you should do this:

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

You're using the line times 510-($-$$) db 0 at the end of kernel.asm. You should use times 512 - ($ - $$) db 0 instead, to fill the entire sector, not just up to 510 bytes.



来源:https://stackoverflow.com/questions/64819255/load-sectors-to-ram-in-qemu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!