将扇区加载到Qemu中的RAM [英] Load Sectors to RAM in qemu
问题描述
我编写了一个简单的程序,将扇区(扇区编号2)加载到RAM
I code a simple program which loads the sector (sector num.2) to the RAM
但不打印任何内容.
首先,我为启动扇区尝试了以下代码:
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
没有用
搜索后,我尝试了这段代码(只是在末尾添加了寄存器:/):
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
再次无效
我使用的命令行:
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有问题吗?
有人可以帮助我解决我的问题吗?
can anyone help me with my problem?
预先感谢
推荐答案
您的代码有几个问题.首先,最重要的是:
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
这仅在从驱动器单元零启动时有效.默认情况下,qemu似乎将您的映像设置为驱动器单元80h(hda =第一个硬盘).您假设您是从单元0(fda =第一张软盘)装入的.因此,您需要使用参数 -fda code.bin
告诉qemu将文件用作软盘映像,和/或删除修改 dl
的行以使用ROM-BIOS初始化的从加载单元到将控制权转移到加载器之前.
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.
您已经修改了加载器以设置段寄存器.尤其需要将 ds
设置为1000h,因为您的内核(隐式)使用该段寄存器来访问其消息.(您的kernel.asm没有 org
行,因此NASM在这里使用其默认的 org 0
.)除了在引导加载程序中设置 ds
之外,您还可以在kernel.asm的开头添加以下内容:
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
这会将 ds
设置为 cs
的值.在Real 86模式下,这对于获取具有与代码段相同的基地址(但具有读/写权限)的数据段引用是有效的.
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).
除了设置 ss
外,还应该设置 sp
.您应在紧随其后的指令中将 sp
设置为设置 ss
的代码.示例:
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
这会将 sp
设置为等于零.由于存在下溢,第一个使用的堆栈插槽将位于 ss:0FFFEh
(完整的64 KiB段的顶部).
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).
在 Kernel_Exit
中,您正在使用21h中断服务4Ch.在此环境中,您无法使用此服务.您应该使用其他内容,例如:
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
或者这个:
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
这只是偶然发生,因为每次您使用 Next_Line
时,您以前使用的 Read
都会在显示终止13(CR =回车)时结束.更一般地说, Next_Line
应该首先显示13(CR),然后显示10(LF =换行).也就是说,您应该这样做:
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
您正在kernel.asm末尾使用 times 510-($-$$)db 0
这行.您应该改用 times 512-($-$$)db 0
填充整个扇区,而不仅仅是510字节.
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.
这篇关于将扇区加载到Qemu中的RAM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!