Here's我的启动加载程序代码,here's一个文档显示寄存器的图片(如果我的错误很重要),内存位于0x10000(其中我告诉引导装载程序加载内核),内核的源程序集以及Qemu运行时的屏幕输出。
kernelStub.bin在一开始就有EB 1B(右跳命令)。 hda.img在第二部门开始时55 AA后立即获得EB 1B。进位标志在我的load_mem子程序中是清楚的,表明它认为负载是好的。所有字节都在内存中,除了前两个总是63 61。
为什么load_mem例程总是将扇区2的前两个字节加载到地址0x10000错误然后得到其余部分?
引导加载程序代码:
更新:根据Matthew Slattery的更正,将jmp SYSADDR:0000
更改为jmp 0x1000:0x0000
。
;Very minimal boot loader
BITS 16 ;Tell assembler to use 16-bit mode
jmp start ;Jump over defines
SYSADDR dw 0x1000 ;Load system at 0x10000
DRIVENUM db 0x80 ;Variable for drive number
HEADNUM db 0
CYLNUM db 0 ;Low bits of cylinder number
SECTNUM db 2 ;Bits 6 and 7 high bits of cylinder number (0),
;Bits 0-5 starting sector number (2)
NUMKERNELSECTS db 0x01 ;Will Probably Change! Number of sectors
;to read from disk
load_msg db 'Loading OS', 0
msg_2 db 'carry flag not clear', 0
load_worked db 'Load worked', 0
start:
mov ax, 0x07C0 ;Set data segment to where BIOS loaded boot loader
mov ds, ax
mov si, load_msg ;Simple text string to indicate loading
call show_message
call load_mem ;Subroutine to load bytes from disk to location
;pointed to by es
jmp 0x1000:0x0000
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Subroutines
;;;Show Message;;;
show_message:
mov ah, 0x0E ;int 0x10 print character to screen function
.repeat:
lodsb ;Get char pointed to by si, puts in al
cmp al, 0 ;see if char is 0 (null)
je .done ;null signifies done
int 0x10 ;If not null, print to screen
jmp .repeat ;Get next char
.done:
ret
;;;Load Memory;;;
load_mem:
xor ah, ah ;ah=0, reset drive
int 0x13 ;Call drive reset
mov ax, [SYSADDR]
mov es, ax ;Destination- es:bx
mov bx, 0
mov dl, [DRIVENUM]
mov dh, [HEADNUM]
mov al, [NUMKERNELSECTS]
mov ch, [CYLNUM]
mov cl, [SECTNUM]
mov ah, 0x02 ;ah=2, read drive
int 0x13 ;Call read interrupt
jnc exit ;If carry flag is clear, exit
exit:
ret
times 510 - ($-$$) db 0;Pad sector with 0
dw 0xAA55 ;Boot signature
答案 0 :(得分:4)
SYSADDR dw 0x1000 ;Load system at 0x10000 ... jmp SYSADDR:0000
没有按你的意愿行事。 SYSADDR
是您想要的值的位置(0x0002
此处),而不是值本身。
我认为执行0x0002:0000
处的任何事情(它甚至不是真正的代码;它是中断向量表的一部分)会导致您的数据被潦草地写下来。
(顺便说一下,还有至少一个问题:第二个链接文档中的内核存根代码没有重置ds
。)
编辑:
我看到你现在已经开始工作了,但为了完整起见,我有一个
因此,对这两个字节中的神秘值进行了完整的解释
jmp SYSADDR:0000
错误:
0002:0000
,即地址0x20
,是INT 08h
的向量。
INT 08h
处理程序的传统入口点地址是f000:fea5
(BIOSes
倾向于保持传统,以便与使用该代码的代码兼容
直接进入点)。所以这个地址的字节几乎可以肯定
是a5 fe 00 f0 ...
。
如果你执行第一个字节a5
,作为代码,那就是movsw
指令,将ds:si
的两个字节复制到es:di
。
ds
仍然是您的引导加载程序的数据段si
指向msg_2
的开头(您的show_message
例程
在打印load_msg
)es
仍然是0x1000
di
大概包含0 所以在jmp 0x0002:0000
之后发生的第一件事是
从c
开始的a
和msg_2
被复制到前两个字节
被装载的部门。
答案 1 :(得分:0)
我找到了有关获取内核here第一次跳转问题的重要细节。我不知道有多少必要(至少有一些BIOS)使用jmp
跟踪nop
。{/ p>
一旦我将nop
放入并设置了我的ds
寄存器,它终于有效了。