在启动级别将C函数与asm代码连接?

时间:2018-01-26 14:34:41

标签: c assembly x86 boot osdev

我正在关注创建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

0 个答案:

没有答案