将扇区加载到Qemu中的RAM [英] Load Sectors to RAM in qemu

查看:90
本文介绍了将扇区加载到Qemu中的RAM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个简单的程序,将扇区(扇区编号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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆