我有一个简单的 32 位内核,它被如下所示的引导加载程序成功加载
[org 0x7c00]
; we can also alter the data segment register (ds) accordingly:
; mov ds, 0x7c0 (it will be 0x7c00 because address bus is 20-bit)
KERNEL_LOCATION equ 0x1000
BOOT_DISK equ 0
; setting up the stack and tiny memory model
xor ax, ax
mov es, ax
mov ds, ax
mov bp, 0x8000
mov sp, bp
; loading the kernel in memory location 0x1000
call read_disk
; ; Set up VESA graphics mode (example: mode 0x101 - 640x480, 16 colors)
; mov ax, 0x4F02 ; VESA function to set video mode
; mov bx, 0x101 ; Mode number for desired resolution/color depth
; int 0x10 ; Call BIOS interrupt to set the video mode
; initialize protected mode
init_pm:
; clear the screen using bios before disabling it
mov ax, 0x0003
int 10h
; clear interrupts
mov bx,suc
;call print_string
; some delay just for looking cool :)
;call delay
;mov ax, 0x0003
;int 10h
cli
; this instruction loads the gdt location and size into the gdtr (gdt register) in the cpu
lgdt [GDT_descriptor]
; changing the first bit of cr0 register (0th control register) which corresponds to [ Protected Mode Enable ]
mov eax, cr0
or eax, 1
mov cr0, eax
; far jump!!
jmp CODE_SEG:start_protected_mode
%include "gdt.asm"
%include "read_disk.asm"
;%include "print_string.asm"
%include "delay.asm"
; this tells the assembeler (in this case nasm) to compile the
; code to 32 bit machine code now on
[bits 32]
start_protected_mode:
; changing stack and memory segments model
mov eax, DATA_SEG
mov ds, eax
mov ss, eax
mov es, eax
mov fs, eax
mov gs, eax
mov ebp, 0x90000 ; 32 bit stack base pointer
mov esp, ebp
jmp KERNEL_LOCATION
suc:
db "entering 32-bit mode...",0
jmp $
times 510-($-$$) db 0
dw 0xaa55
我的问题是我的内核 .text 部分将覆盖内核的其他部分,因此导致随机行为
这是用c:编写的内核代码
#include "std/stdout.h"
#include "terminal/terminal.h"
void func1(){
for (int i = 0; i < 33; i++)
{
/* code */
}
}
void func2(){
for (int i = 0; i < 33; i++)
{
/* code */
}
}
void func3(){
for (int i = 0; i < 33; i++)
{
/* code */
}
}
void func4(){
for (int i = 0; i < 33; i++)
{
/* code */
}
}
void kernel_start(){
prepare_terminal();
background_color = 32;
}
注意:不知何故,只有其中 3 个函数不会导致问题,因此我怀疑再添加一个函数会超出某种限制
我尝试更改链接器脚本以添加对齐,因为我怀疑这是由于每个部分的大小有限,但它没有帮助,或者也许我做错了
这是我当前的链接器脚本:
ENTRY(_start)
SECTIONS {
. = 0x1000;
.text : {
*(.text)
}
.data : {
*(.data)
}
.bss : {
*(.bss)
}
}
损坏的代码:
正常:
原来我的问题是因为我只从磁盘读取了10个扇区,这导致程序中途停止并产生一些意想不到的问题。
我所做的是增加要读取的扇区数量:
read_disk:
; bios read functions
mov ah, 0x02
; number of sectors to be read
; mov al, 10 <========! HERE
mov al, 40
; chs addressing
mov ch, 0x00 ; cylender
mov dh, 0x00 ; head
mov cl, 0x02 ; sector (reading the first sector after the boot sector sectors start at 1)
; setting the bx to the address we want to load our read disk
mov bx, KERNEL_LOCATION
mov dl, BOOT_DISK
int 0x13
; jump to error handler if c flag is one
; jc disk_error
; returning to the caller address
ret
; error handler
disk_error:
mov bx, error_msg
;call print_string
jmp $
error_msg:
; null terminating string :)
db "error reading disk",0
它解决了我的问题:)