Assembly 复制并执行
我正在为我的定制内核编写一个简单的引导程序。它的逻辑非常简单:Assembly 复制并执行,assembly,x86,bootloader,Assembly,X86,Bootloader,我正在为我的定制内核编写一个简单的引导程序。它的逻辑非常简单: 引导加载程序由BIOS加载 将自身复制到0x8000 将内核从磁盘加载到0x9000 跳转到0x8000并将内核复制到0x0并设置GDT 跳转到0x0 这是我的引导程序: .set DEST, 0x8000 start: movw $0x3, %ax int $0x10 movw msg, %bp movw $0xa, %cx call print_msg //copy the end o
.set DEST, 0x8000
start:
movw $0x3, %ax
int $0x10
movw msg, %bp
movw $0xa, %cx
call print_msg
//copy the end of bootloader to new place
selfCopy:
cld
xor %ax, %ax
movw %ax, %ds
movl move_kernel, %esi
movw %ax, %es
movl DEST, %edi
movl (move_kernel_end-move_kernel), %ecx
rep movsb
//load kernel to 0x9000
load_kernel:
xor %dx, %dx
xor %ah, %ah
int $0x10
jc reboot
xor %ax, %ax
movw %ax, %ds
movb $0x42, %ah
movw DAP, %si
int $0x13
jc reboot
jmp DEST
DAP:
.byte 0x10
.byte 0x0
.word 2048
//offset
.word 9000
.word 0x0
.long 1
move_kernel:
xor %ax, %ax
movw %ax, %ds
movl $0x9000, %esi
movw %ax, %es
movl $0x0, %edi
movl (move_kernel_end-move_kernel), %ecx
rep movsb
lgdt gdtr
jmp $0x0
move_kernel_end:
print_msg:
//print message
movw $0x0007, %bx
movw $0x1301, %ax
int $0x10
ret
msg:
.string "Booting..."
error_msg:
.string "Error..."
gdt:
.quad 0x0
.byte 0x0
.byte 0b11001111
.byte 0b11111010
.byte 0x0
.word 0x0
.word 0xffff
.byte 0x0
.byte 0b11001111
.byte 0b11110010
.byte 0x0
.word 0x0
.word 0xffff
gdtr:
.long gdt
.word $23
reboot:
movw error_msg, %bp
movw $0x8, %cx
call print_msg
jmp .
.fill 510-(. - start), 1, 0
.byte 0x55
.byte 0xaa
所以,如果我把jmp.
放在jmpdest
之前,它就不会进入无限循环。那么,我的引导程序有什么问题
谢谢
顺便说一句,对不起,我的英语不好
修改代码:
.set DEST, 0x8000
start:
movw $0x3, %ax
int $0x10
pushw msg
pushw $0xa
call print_msg
//copy the end of bootloader to new place
selfCopy:
cld
xor %ax, %ax
movw %ax, %ds
movl move_kernel, %esi
movw %ax, %es
movl DEST, %edi
movl (move_kernel_end-move_kernel), %ecx
rep movsb
//load kernel to 0x9000
load_kernel:
xor %dx, %dx
xor %ah, %ah
int $0x13
jc reboot
xor %ax, %ax
movw %ax, %ds
movb $0x42, %ah
movw DAP, %si
int $0x13
jc reboot
jmp DEST
DAP:
.byte 0x10
.byte 0x0
.word 2048
//offset
.word 9000
.word 0x0
.long 1
move_kernel:
cli
xor %ax, %ax
movw %ax, %ds
movl $0x9000, %esi
movw %ax, %es
movl $0x0, %edi
movl (move_kernel_end-move_kernel), %ecx
rep movsb
lgdt gdtr
jmp .
sti
jmp $0x0
move_kernel_end:
print_msg:
//print message
popw %ax
popw %cx
popw %bp
pushl %eax
movb $0x07, %bl
movb $0x13, %ah
movb $0x1, %al
int $0x10
ret
msg:
.string "Booting..."
gdt:
.quad 0x0
.byte 0x0
.byte 0b11001111
.byte 0b11111010
.byte 0x0
.word 0x0
.word 0xffff
.byte 0x0
.byte 0b11001111
.byte 0b11110010
.byte 0x0
.word 0x0
.word 0xffff
gdtr:
.long gdt
.word 23
reboot:
pushw $0xdead
pushw $0x8
call print_msg
.fill 510-(. - start), 1, 0
.byte 0x55
.byte 0xaa
在您的
load\u内核:
标签下面,您打算执行int$0x10
还是int$0x13
?我看不到在哪里显式加载了%es
0:0
似乎是将内核复制到的一个奇怪的位置-至少没有cli
!您没有向我们显示您的ld命令行或链接器脚本。初始消息有效吗?感谢您的更正!我已经修改了代码(将其添加到问题中),所以我遇到了下一个问题:它在int%0x13
(在内核加载期间)崩溃。我通过异或%ax、%ax movw%ax、%es设置了%es
,因此%es
==0。在这个阶段,我根本不使用链接器(bootloader是yasm-f bin的原始二进制文件)。另外,我的软盘映像不正确,只有514字节。这个问题会发生吗?它是如何崩溃的?如果设置了CF,您可以检查AH的状态。顺便说一句,0x0真的不是内核的好地方。Bochs:[GDBST]用ac0停止GDB:info寄存器eax eflags
:eflags 0x0[]
eax 0x2fe 766代码>为什么0x0
不是个好地方(我不会使用BIOS中断)?啊!使用Yasm!酷!这可能意味着您的原点是0,而不是0x7C00,因此%ds
和%es
应该是0x7C0而不是0。中断会发生-每18秒,每次按键和释放,也许其他时间-无论你是否使用它们。。。除非你把它们关掉,我看不到。我不知道Bochs,所以我不明白它在告诉你什么,抱歉。