Wednesday, 11 September 2013

Trouble with Assembly: Creating a Bootloader

Trouble with Assembly: Creating a Bootloader

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:
1) How I allocate stack space, or 2) How I set registers before calling
INT 0x13
Can anyone help me out by telling me what's wrong?

No comments:

Post a Comment