assembly Bootloader和Kernel:仅在屏幕上显示光标

oknwwptz  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(79)

我目前正在开发一个使用自定义 Bootstrap 和内核的简单操作系统。然而,当我 Boot 我的系统时,它只在屏幕上显示一个光标,并不显示任何进一步的输出。我正在寻找有关如何解决此问题的一些指导。
以下是关于我的设置的一些细节:
我有一个用汇编语言编写的自定义 Bootstrap (bootloader.asm),它将内核加载到内存中。
我的内核是用汇编(kernel.asm)编写的,包含基本的初始化代码。
我使用NASM汇编代码,使用LD将目标文件链接在一起。
我正在物理硬件上测试操作系统。
通过检查指定位置的内存内容,我验证了引导加载程序正在正确地将内核加载到内存中。
我在引导装载程序和内核代码中添加了调试输出语句,以检查它们是否按预期执行。但是,我在屏幕上看不到光标以外的任何输出。
我怀疑我的代码或配置可能存在问题,导致操作系统无法正确初始化并在屏幕上显示输出。
有人能指导我如何进一步解决这个问题,并让我的操作系统显示预期的输出吗?
任何见解,建议或调试技术将不胜感激。
引导装载程序:

[BITS 16]
[ORG 0x7C00]

section bootloader

jmp main

main:
    ; Set up segment registers
    mov ax, 0x07C0
    mov ds, ax
    mov es, ax

    ; Load the kernel into memory
    mov bx, 0x8000      ; Destination memory address
    mov ah, 0x02        ; Read sector function
    mov al, 1           ; Number of sectors to read
    mov dl, 0x80        ; Boot drive number
    mov ch, 0           ; Cylinder number
    mov dh, 0           ; Head number
    mov cl, 2           ; Sector number
    int 0x13            ; Disk interrupt

    ; Jump to the loaded kernel
    jmp 0x8000:0000

times 510 - ($ - $$) db 0
dw 0xAA55 ; Boot signature

字符串
内核(我也决定在内核中有一个UI):

[BITS 16]
[ORG 0x8000]

section kernel

start:
    mov ax, 0x07C0  ; Set up segment registers
    mov ds, ax
    mov es, ax

    ; Clear the screen
    mov ah, 0x00    ; Video BIOS - Set video mode
    mov al, 0x03    ; Mode 3 (Text mode: 80x25, 16 colors)
    int 0x10        ; Video interrupt

    ; Print the menu options
    mov si, menu
    call printString

    ; Wait for user input
    call readChar

    ; Process user input
    cmp al, '1'
    je option1
    cmp al, '2'
    je option2
    jmp invalidOption

option1:
    mov si, msgOption1
    call printString
    jmp end

option2:
    mov si, msgOption2
    call printString
    jmp end

invalidOption:
    mov si, msgInvalid
    call printString

end:
    ; Halt the system
    cli
    hlt

printString:
    lodsb           ; Load the next character from string
    test al, al     ; Check if end of string
    jz done         ; If yes, return
    mov ah, 0x0E    ; Video BIOS - Teletype output
    mov bh, 0x00    ; Video page
    int 0x10        ; Video interrupt
    jmp printString ; Print next character

done:
    ret

readChar:
    mov ah, 0x00    ; BIOS - Wait for key press
    int 0x16        ; Keyboard interrupt
    ret

menu db 'Welcome to aiOS!', 0x0D, 0x0A, 'Select an option:', 0x0D, 0x0A, '1. Option 1', 0x0D, 0x0A, '2. Option 2', 0x0D, 0x0A, 0x00
msgOption1 db 'You selected Option 1.', 0x0D, 0x0A, 0x00
msgOption2 db 'You selected Option 2.', 0x0D, 0x0A, 0x00
msgInvalid db 'Invalid option.', 0x0D, 0x0A, 0x00

times 510 - ($ - $$) db 0
dw 0xAA55 ; Boot signature

hivapdat

hivapdat1#

您有几个与段:偏移寻址有关的混淆。如果你想看评论,请看What are the segment and offset in real mode memory addressing?

  • 您的int 0x13读入es:bx,这里是0x07c0:0x8000。这转换为线性地址0xfc00,这不是您想要的。
  • 类似地,[ORG 0x7c00][ORG 0x8000]告诉汇编程序假设代码将在该 * 偏移量 * 处加载。例如,假设menu的地址类似于0x8055。这意味着mov si, menumov si, 0x8055,而您的printString将从地址0x07c0:0x8055读取(因为ds = 0x07c0),这又是错误的。

也许最简单和最不容易混淆的修复方法是用零加载dses,而不是0x07c0。然后将“kernel”扇区读入0x0000:0x8000,在0x0000:0x8055访问menu,所有内容都与当前的ORG指令一致。
作为一个单独的问题,在jmp 0x8000:0000中,您反转了段和偏移。即使8086是little-endian并且偏移量被放置在内存中的段之前,在汇编语言源代码中,您仍然使用seg:ofs顺序。因此,将其设置为jmp 0x0000:0x8000

相关问题