user2770595
user2770595

Reputation: 1

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?

Upvotes: 0

Views: 709

Answers (1)

Jester
Jester

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

Related Questions