我目前正在开发一个使用自定义 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
型
1条答案
按热度按时间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, menu
是mov si, 0x8055
,而您的printString
将从地址0x07c0:0x8055
读取(因为ds = 0x07c0
),这又是错误的。也许最简单和最不容易混淆的修复方法是用零加载
ds
和es
,而不是0x07c0
。然后将“kernel”扇区读入0x0000:0x8000
,在0x0000:0x8055
访问menu
,所有内容都与当前的ORG
指令一致。作为一个单独的问题,在
jmp 0x8000:0000
中,您反转了段和偏移。即使8086是little-endian并且偏移量被放置在内存中的段之前,在汇编语言源代码中,您仍然使用seg:ofs
顺序。因此,将其设置为jmp 0x0000:0x8000
。