繁体   English   中英

装配麻烦:创建一个Bootloader

[英]Trouble with Assembly: Creating a Bootloader

我刚刚启动了一个操作系统类,并在臭名昭着的bootloader实验室中遇到了障碍。 分配的一部分是在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"

现在,我的代码打印了它应该的所有消息,但是当它是时候跳进内核时,它显然没有正确地执行它(内核不显示确认消息)。

我的代码编译,但我觉得必须在某处出现错误:

  1. 我如何分配堆栈空间,或
  2. 如何在调用INT 0x13之前设置寄存器

谁能告诉我什么是错的,可以帮助我吗?

您显然在地址0:0x1000处加载代码0:0x1000es=0bx=0x1000 )但跳转到0x1000:0ljmp $0x1000, $0x0 )。 这不起作用,因为第一个是物理地址0x1000但第二个是0x10000(因为在实模式中你必须将段乘以16)。 让它们匹配。

可能存在其他错误,学习使用调试器或者您每分钟都会寻求帮助。

另外,请保留格式,以便我们可以轻松地复制粘贴整个代码以进行自我测试(或者也提供一个pastebin链接)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM