我刚开始上操作系统课程,但在臭名昭著的引导加载程序实验室遇到了障碍。任务的一部分是在 Assembly 中创建一个 512 字节的引导加载程序,能够或多或少地从头开始加载给定的内核。这是我到目前为止工作的代码:
# bootblock.s
# .equ symbol, expression
# These directives set the value of the symbol to the expression
.equ BOOT_SEGMENT,0x07c0
.equ DISPLAY_SEGMENT,0xb800
.text # Code segment
.globl _start # The entry point must be global
.code16 # Real mode
# Start
_start:
jmp over
# OS Size
os_size:
# Area reserved for createimage to write the OS size
.word 0
.word 0
# Routines to print a zero terminated string pointed to by esi
# Overwrites: AX, DS, BX
print:
movw $BOOT_SEGMENT,%ax
movw %ax,%ds
print_loop:
lodsb
cmpb $0,%al
je print_done
movb $14,%ah
movl $0x0002,%ebx
int $0x10
jmp print_loop
print_done:
retw
# Over is where the magic happens
over:
movl $messagetest, %esi
call print
movl $hellostring, %esi
call print
# Allocating the stack
movw $0x0, %ax
movw %ax, %ss
movw $0xffff, %sp
# Booting up at 0x07c0
movw $BOOT_SEGMENT, %ax
movw %ax, %ds
movl $messageboot, %esi
call print
# Resetting the disk drive, setting %dl and calling int 0x13
movb $0x0, %ah
movb $0x80, %dl
int $0x13
# Make says my .os_size = 9 sectors. Setting %al = 9
movb $0x09, %al
# %cl controls which sector to read from. Setting %cl = 2
movb $0x02, %cl
# %dh/%ch control head numbers. I'm not sure how they work; setting them to zero
movb $0x0, %dh
movb $0x0, %ch
# Setting the drive number to 0x80 (Hard drive)
movb $0x80, %dl
# Time to set es:bx to read from the correct place (0:1000)
movw $0x0, %bx
movw %bx, %es
movw $0x1000, %bx
# Setting %ah = 2 and calling int 0x13 again (Read Sectors)
movb $0x02, %ah
int $0x13
# Setting %ds = 0. I don't think it can be done directly.
movw $0x0, %ax
movw %ax, %ds
# Kernel jump
movl $messageready, %esi
call print
ljmp $0x1000, $0x0
# Displaying error message, if any
movl $messageerror, %esi
call print
# Rebooting the OS
reboot:
movl $messagereboot, %esi
call print
movb $0, %ah
int $0x16
movb $0, %ah
int $0x19
# Infinite loop
forever:
hlt
jmp forever
# Error handling
error:
movl $messageerror, %esi
call print
# Test messages
hellostring:
.asciz "Hi Professor.\n\n\r"
messagetest:
.asciz "\nTesting Bootblock!\n\r"
messageboot:
.asciz "Booting up... \n\r "
messageready:
.asciz "\b>> Jumping into the Kernel... \n\r"
messagereboot:
.asciz "Press any key to reboot the OS!\n\r"
messageerror:
.asciz "Unknown error!\n\r"
现在,我的代码打印了它应该打印的所有消息,但是当需要跳转到内核时,它显然没有正确执行(内核不显示确认消息)。
我的代码可以编译,但我觉得某处一定有错误:
- 我如何分配堆栈空间,或者
- 在调用 INT 0x13 之前如何设置寄存器
任何人都可以通过告诉我出了什么问题来帮助我吗?