Reputation: 1
I just started an Operating Systems class and have run into a wall on the infamous bootloader lab. One part of the assignment is to create a 512-byte bootloader in Assembly capable of loading a given kernel, more or less from scratch. Here's the code I've worked on so far:
# 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"
Now, my code prints all of the messages it is supposed to, but when it is time to jump into the kernel, it's clearly just not doing it properly (the kernel doesn't display a confirmation message).
My code compiles, but I feel there must be an error somewhere either in:
Can anyone help me out by telling me what's wrong?
Upvotes: 0
Views: 709
Reputation: 58762
You are apparently loading the code at address 0:0x1000
(es=0
, bx=0x1000
) but jumping to 0x1000:0
(ljmp $0x1000, $0x0
). That won't work since the first is physical address 0x1000 but the second is 0x10000 (because in real mode you have to multiply segment by 16). Make them match.
There may be other errors, learn to use a debugger or you'll be asking for help every minute.
Also, please keep the formatting such that we can easily copy-paste the whole code for testing ourselves (or provide a pastebin link too).
Upvotes: 2