我正在尝试制作自己的操作系统,但目前遇到了一个小问题。我的欢迎消息无法在终端中加载。
除此之外,一切似乎都运行良好(我不确定是否还有其他错误)
以下是 QEMU 运行后显示的内容
make clear
make
make run
这是我的档案,供参考。
内核
/* kernel.c - Main kernel entry point */
/* Video memory address */
#define VIDEO_MEMORY 0xB8000
/* Color: white on black */
#define COLOR 0x0F
/* Function to write a character to video memory */
void putchar(char c, int x, int y) {
unsigned char *video_memory = (unsigned char*)VIDEO_MEMORY;
int offset = (y * 80 + x) * 2;
video_memory[offset] = c;
video_memory[offset + 1] = COLOR;
}
/* Function to clear the screen */
void clear_screen() {
unsigned char *video_memory = (unsigned char*)VIDEO_MEMORY;
for(int i = 0; i < 80 * 25 * 2; i += 2) {
video_memory[i] = ' ';
video_memory[i + 1] = COLOR;
}
}
/* Function to print a string */
void print_string(const char *str, int x, int y) {
int i = 0;
while(str[i] != '\0') {
putchar(str[i], x + i, y);
i++;
}
}
/* Main kernel function */
void kernel_main() {
// Clear screen
clear_screen();
// Display a welcome message
print_string("NOX OS Kernel Loaded Successfully!", 20, 10);
print_string("Welcome to the dark side...", 25, 12);
// Halt the CPU
while(1) {
__asm__ volatile("hlt");
}
}
链接器.ld
ENTRY(_start)
SECTIONS {
. = 0x1000; /* Match the address in the bootloader */
.text : {
*(.text)
}
.data : {
*(.data)
}
.bss : {
*(.bss)
}
}
启动文件
; boot.asm - A simple bootloader
[bits 16]
[org 0x7c00]
; Set up segments
cli
mov ax, 0
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00
sti
; Display a message
mov si, boot_message
call print_string
; Load the kernel from disk
mov ah, 0x02 ; BIOS read sector function
mov al, 15 ; Number of sectors to read (adjust as needed)
mov ch, 0 ; Cylinder number
mov cl, 2 ; Sector number (sectors start from 1, bootloader is at 1)
mov dh, 0 ; Head number
mov dl, 0 ; Drive number (0 = floppy disk)
mov bx, 0x1000 ; Memory location to load the kernel
int 0x13 ; Call BIOS interrupt
jc disk_error ; Jump if error (carry flag set)
; Switch to protected mode
cli ; Disable interrupts
lgdt [gdt_descriptor] ; Load GDT
; Set protected mode bit
mov eax, cr0
or eax, 0x1
mov cr0, eax
; Far jump to 32-bit code
jmp CODE_SEG:protected_mode_entry
disk_error:
mov si, disk_error_msg
call print_string
jmp hang
; Infinite loop for when we're done
hang:
jmp hang
; Print string routine
print_string:
lodsb
or al, al
jz done
mov ah, 0x0E
int 0x10
jmp print_string
done:
ret
; Global Descriptor Table
gdt_start:
; Null descriptor
dd 0x0
dd 0x0
; Code segment descriptor
dw 0xffff ; Limit (bits 0-15)
dw 0x0000 ; Base (bits 0-15)
db 0x00 ; Base (bits 16-23)
db 10011010b ; Access byte
db 11001111b ; Flags and Limit (bits 16-19)
db 0x0 ; Base (bits 24-31)
; Data segment descriptor
dw 0xffff ; Limit
dw 0x0000 ; Base (bits 0-15)
db 0x00 ; Base (bits 16-23)
db 10010010b ; Access byte
db 11001111b ; Flags and Limit
db 0x0 ; Base (bits 24-31)
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; GDT size
dd gdt_start ; GDT address
; Constants
CODE_SEG equ 0x08
DATA_SEG equ 0x10
; Messages
boot_message db 'NOX OS Booting...', 0
disk_error_msg db 'Error loading kernel!', 0
[bits 32]
protected_mode_entry:
; Set up segment registers for protected mode
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Set up a stack
mov esp, 0x90000
; Far jump to the kernel using a code segment selector
jmp CODE_SEG:0x1000
; Padding and boot signature
times 510-($-$$) db 0
dw 0xAA55
入口文件
; entry.asm - Assembly entry point that calls our C kernel
[bits 32]
[global _start]
[extern kernel_main] ; Make sure this matches your C function name
section .text
_start:
; We're already in protected mode, skip trying to use BIOS interrupts
; Show a debug character at position 3
mov byte [0xB8004], 'E'
mov byte [0xB8005], 0x07
; Set up kernel stack
mov esp, kernel_stack_top
; Call the C kernel main function
call kernel_main
; Kernel should never return, but if it does:
cli ; Disable interrupts
hlt ; Halt the CPU
jmp $ ; Infinite loop
; Reserve space for the kernel stack
section .bss
align 16
kernel_stack_bottom:
resb 16384 ; 16 KB for kernel stack
kernel_stack_top:
Makefile
# Compiler settings
CC = x86_64-elf-gcc
CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -Wall -Wextra -c
ASM = nasm
ASMFLAGS = -f elf32
LD = x86_64-elf-ld
LDFLAGS = -T src/kernel/linker.ld -m elf_i386
# Directories
SRC_DIR = src
BUILD_DIR = build
# Files
BOOT_SRC = $(SRC_DIR)/boot/boot.asm
KERNEL_ENTRY = $(SRC_DIR)/kernel/entry.asm
KERNEL_SRC = $(SRC_DIR)/kernel/kernel.c
BOOT_BIN = $(BUILD_DIR)/boot.bin
KERNEL_OBJ = $(BUILD_DIR)/kernel.o
ENTRY_OBJ = $(BUILD_DIR)/entry.o
KERNEL_BIN = $(BUILD_DIR)/kernel.bin
OS_IMAGE = $(BUILD_DIR)/nox-os.img
# Build rules
all: $(OS_IMAGE)
$(BOOT_BIN): $(BOOT_SRC)
$(ASM) -f bin $< -o $@
$(ENTRY_OBJ): $(KERNEL_ENTRY)
$(ASM) $(ASMFLAGS) $< -o $@
$(KERNEL_OBJ): $(KERNEL_SRC)
$(CC) $(CFLAGS) $< -o $@
$(KERNEL_BIN): $(ENTRY_OBJ) $(KERNEL_OBJ)
$(LD) $(LDFLAGS) -o $@ $^
$(OS_IMAGE): $(BOOT_BIN) $(KERNEL_BIN)
dd if=/dev/zero of=$@ bs=512 count=2880
dd if=$(BOOT_BIN) of=$@ conv=notrunc
# Ensure the kernel is properly aligned at sector 2
dd if=$(KERNEL_BIN) of=$(OS_IMAGE) seek=1 conv=notrunc bs=512
run: $(OS_IMAGE)
qemu-system-i386 -fda $(OS_IMAGE) -boot a -monitor stdio -d int -no-reboot
clean:
rm -rf $(BUILD_DIR)/*
mkdir -p $(BUILD_DIR)
尝试增加读取的扇区boot.asm
,但也没有用