从x64系统到x32二进制交叉编译c内核

问题描述 投票:1回答:1

我正在尝试出于教育目的创建OS内核。使用this指南,我用fasm编写了一个引导加载程序:

use16
org 0x7c00

start:
    jmp kernel_start

KERNEL_OFFSET equ 0x1000


gdt_start:

gdt_null:
    dd 0x0
    dd 0x0

gdt_code:
    dw 0xffff
    dw 0x0000
    db 0x00
    db 10011010b
    db 11001111b
    db 0x00

gdt_data:
    dw 0xffff
    dw 0x0000
    db 0x00
    db 10010010b
    db 11001111b
    db 0x00

gdt_end:

gdt_descriptor:
    dw gdt_end - gdt_start - 1
    dd gdt_start



CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start



read_disk:
    pusha
    push dx

    mov ah, 0x02
    mov al, dh
    mov ch, 0x00
    mov dh, 0x00
    mov cl, 0x02

    int 0x13

    jc .disk_error

    pop dx
    cmp dh, al
    jne .disk_error
    jmp .done

.disk_error:
    mov bx, ERROR_MSG
    call write_string
    stc

.done:
    popa
    ret


write_string:
    pusha
    mov ah, 0x0e

.repeat:
    lodsb
    cmp al, 0x00
    je .done
    int 0x10
    jmp .repeat

.done:
    popa
    ret



kernel_start:
    mov [BOOT_DRIVE], dl

    cli
    mov ax, cs
    mov ss, ax
    mov sp, start
    mov bp, start
    sti

    mov ds, ax
    mov es, ax

    mov si, BOOT_MSG
    call write_string

    mov dh, 15
    mov dl, [BOOT_DRIVE]
    mov bx, KERNEL_OFFSET
    call read_disk

    cli
    lgdt [gdt_descriptor]
    mov eax, cr0
    or eax, 0x01
    mov cr0, eax

    jmp CODE_SEG:kernel_launch



use32

kernel_launch:

    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov ebp, start
    mov esp, start

    call KERNEL_OFFSET

    jmp $



variables:
    BOOT_DRIVE db 0
    KERNEL_LEN file "kernel_info.bb": 0x0, 1
    BOOT_MSG   db "Booted in real mode...", 0x0d, 0x0a, 0
    ERROR_MSG  db "Could not load second boot loader!", 0x0d, 0x0a, 0

magic_numbers:
    times 510-($-$$) db 0
    dw 0xaa55

我已经用fasm loader.asm进行编译,并使用dd制作了iso。它在OracleVM中可以正常打印消息。

现在是时候将其与c部分结合了。但是问题是:我无法在目标(x32)设备上构建。我被迫使用x64。根据this手册,我找到了一种编译elf可执行文件并将其与multiboot链接的方法。但是我不想使用multiboot标准,我宁愿使用自写的bootloader(上面的那个)。

我应该使用哪些工具,参数和配置来将C代码编译为x32,将其与汇编器部件链接并创建二进制文件?还是我应该分别编译assempler-part二进制文件和c-part,然后将它们依次写入磁盘映像?

到目前为止,我在互联网上找不到任何答案。 是否有可能将这两个内核部分放在一起?

这是我的C代码:

void main() {
    char* video_memory = 0xb8000;
    *video_memory = ’X’;
}

更新:我尝试了以下命令:

$nasm loader.asm -f bin -o loader.bin
$gcc -m32 -fno-pie -ffreestanding -c kernel.c -o kernel.o
$ld -m -elf_i386 -o kernel.bin -Ttext 0x1000 kernel.o --oformat binary
$cat loader.bin kernel.bin > os-image

将引导程序和内核编译为二进制文件,然后将它们写入磁盘映像。 Bootloader可以正常工作,但是没有显示来自内核的消息。

c kernel cross-compiling bootloader fasm
1个回答
0
投票

我发现了一个错误(以防有人遇到相同的问题),构建脚本存在问题,我应该使用:

$ gcc -m32 -ffreestanding -c kernel.c -o kernel.o

而不是:

$ gcc -m32 -fno-pie -ffreestanding -c kernel.c -o kernel.o

((在-fno-pie标志中不需要)。

也是命令:

$ ld -m -elf_i386 -o kernel.bin -Ttext 0x1000 kernel.o --oformat binary

应该分成两部分:

$ ld -m -elf_i386 -o kernel.elf -Ttext 0x1000 kernel.o
$ objcopy -O binary kernel.elf kernel.bin

就这样!

© www.soinside.com 2019 - 2024. All rights reserved.