我正在关注创建32位操作系统的教程。我已经设法快乐地切换到32位保护模式,但无法进一步。
下面,boot_sect.asm是主要的汇编代码。在boot_sect.asm中切换到保护模式后,将通过boot_sect.asm中的kernel_entry.asm(调用c函数)调用外部C函数(kmain)。 ram中C函数的位置是0x1000000。
kmain()应该在屏幕上打印x。但是,这不会发生。实际上,为了诊断代码,我在kmain()中放了一个无限的while循环,但是程序没有挂起来;相反,它直接结束。我猜文件没有正确链接或存在内存重叠问题。我无法继续下去,而且我现在陷入困境。
我很感激有任何想法或帮助来克服这一步。
boot_sect.asm(主要的asm代码)
; A boot sector that boots a C kernel in 32-bit protected mode
[bits 16]
[org 0x7c00]
KERNEL_OFFSET equ 0x100000 ; This is the memory offset to where kernel will be loaded
mov [BOOT_DRIVE], dl
mov bp, 0x9000 ; stack origin.
mov sp, bp
mov bx, MSG_REAL_MODE ;print that we are starting
call print_string ; booting from 16-bit real mode
call load_kernel ; Load our kernel
call switch_to_pm ; Switch to protected mode, from which
; we will not return
jmp $
; Include our useful , hard-earned routines
%include "print/print_string.asm"
%include "disk/disk_load.asm"
%include "pm/gdt.asm"
%include "pm/print_string_pm.asm"
%include "pm/switch_to_pm.asm"
[bits 16]
; load_kernel
load_kernel:
mov bx, MSG_LOAD_KERNEL ; Print a message to say we are loading the kernel
call print_string
mov bx, KERNEL_OFFSET ; Set-up parameters for our disk_load routine , so
mov dh, 15 ; that we load the first 15 sectors (excluding
mov dl, [BOOT_DRIVE] ; the boot sector) from the boot disk (i.e. our
call disk_load ; kernel code) to address KERNEL_OFFSET
ret
[bits 32]
BEGIN_PM:
mov ebx, MSG_PROT_MODE ; Use 32-bit print routine to
call print_string_pm ; announce its in protected mode
;the program manages to come here perfectly.
;here the kmain() function is called via kernel_entry.asm
;but after this call, the program gets "lost", it ends somehow.
call KERNEL_OFFSET
;it cant even get here, it ends before getting here. Probably the kmain() is not located at KERNEL_OFFSET due to a problem.
jmp $ ;Hang.
; Global variables
BOOT_DRIVE db 0
MSG_REAL_MODE db "Started in 16-bit Real Mode", 0
MSG_PROT_MODE db "Successfully landed in 32-bit Protected Mode", 0
MSG_LOAD_KERNEL db "Loading kernel into memory.", 0
; Bootsector padding
times 510-($-$$) db 0
dw 0xaa55
kernel.c(c代码)
void kmain()
{
char* screen = (char*)0xb8000;
screen[0] = 'X';
}
kernel_entry.asm(调用c代码)
[bits 32]
[extern _kmain]
call _kmain
jmp $
最后,为了获得os-image,我使用了以下命令
将kernel.c和kernel_entry.asm转换为目标文件(nasm和gcc命令),然后链接它们以创建kernel.bin文件(通过使用ld命令和kmain()的地址0x100000)。然后使用type命令组合kernel.bin和boot_sect.bin以获取操作系统映像。
gcc -m32 -ffreestanding -c kernel.c -o kernel.o
nasm kernel_entry.asm -f elf -o kernel_entry.o
ld -m i386pe -T NUL -o kernel.bin -Ttext-segment 0x100000 kernel_entry.o kernel.o
nasm boot_sect.asm -f bin -o boot_sect.bin
type boot_sect.bin kernel.bin > os-image