c - 如何在准系统上正确执行 C 代码?
问题描述
我正在尝试制作一个没有 GRUB 的操作系统。现在我想从保护模式执行 C 代码,但我不知道如何。
我尝试了这些命令(pm.bin 是编译的 ASM 代码,我想在其中调用 C 代码,而 bootloader.bin 是第一阶段的引导加载程序,它可以正常工作):
nasm -f bin bootloader.asm -o bootloader.bin
nasm -f bin pm.asm -o pm.bin
gcc -ffreestanding -c kernel.c -o kernel.o
ld -o kernel.bin -Ttext 0x0 --oformat binary kernel.o
cat pm.bin kernel.bin > fin.bin
sudo dd if=bootloader.bin ibs=512 count=1 of=boot.img obs=512
sudo dd if=fin.bin ibs=1024 count=1 of=boot.img obs=512 seek=1
sudo qemu-system-x86_64 boot.img -monitor stdio
好的,使用“cat”命令我将在我的二进制 ASM 代码之后得到二进制 C 代码,但我怎样才能跳转到 C 代码?
C 代码(kernel.c):
void main() {
char* vga = (char*)0xb8000;
vga[0] = 'y';
vga[1] = 0x4;
}
引导加载程序.asm:
bits 16
org 0x7c00
jmp start
%include "print_hex.asm"
; ================================================
start:
cli
mov ah, 0x00 ; clearing the screen
mov al, 0x03
int 0x10
xor ax, ax ; segment reg. init
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x07c0 ; stack init
mov [bootdisk], dl
jmp reset
reset:
; reset the disk
xor ax, ax
mov dl, [bootdisk]
int 0x13
jc error
load_disk:
mov bx, 0x07e0 ; загружаем код по адресу 0x7e00
mov es, bx
xor bx, bx ; обнуляем bx, получается 0x07e0:0x0000
mov ah, 0x02 ; функция
mov dl, [bootdisk] ; номер накопителя
mov al, 0x1 ; количество читаемых секторов
mov ch, 0x0
mov cl, 0x2 ; номер сектора
mov dh, 0x0 ; head
int 0x13 ; читаем, используя все параметры
jc error ; если ошибка
jmp 0x07e0:0x0000
error:
mov dx, ax
call print_hex_dx
jmp $
bootdisk: db 0 ; for boot disk number
times 510 - ($ - $$) db 0
dw 0xaa55
pm.asm(我需要从这个文件中调用 C):
bits 16
org 0x7e00
jmp mainf
%include "gdt.inc"
mainf:
cli ; disable interrupts
xor ax, ax ; null segments
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x07c0 ; the stack is under 0x7c00
sti ; enable interrupts
call installGDT ; installing GDT
; entering PM
cli
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x8:final_stage
; =============================================================
[bits 32]
%include "driver_print_string.asm"
%include "color_clear_screen.asm"
; maybe I'll need "extern main" here
final_stage:
cli
mov ax, 0x10
mov ds, ax
mov es, ax
mov ss, ax
mov esp, 0x07c0
disable_cursor:
mov dx, 0x3d4
mov al, 0xa
out dx, al
inc dx
mov al, 0x20
out dx, al
ccode:
; here I want my code to call C, but I don't know how to link it correctly!
jmp $
times 1024 - ($ - $$) db 0
gdt.inc:
installGDT:
cli
pusha
lgdt [toc]
sti
popa
ret
;*******************************************
; Global Descriptor Table (GDT)
;*******************************************
gdt_data:
dd 0 ; null descriptor
dd 0
; gdt code: ; code descriptor
dw 0FFFFh ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
; gdt data: ; data descriptor
dw 0FFFFh ; limit low (Same as code)
dw 0 ; base low
db 0 ; base middle
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
end_of_gdt:
toc:
dw end_of_gdt - gdt_data - 1 ; limit (Size of GDT)
dd gdt_data ; base of GDT
那么如何正确编译和链接 C 和 ASM 代码并跳转到第一个?
解决方案
推荐阅读
- javascript - 如何在 Sigma.js 中隐藏边缘标签
- python - Python sklearn 中 load_breast_cancer() 数据集的对象类型是什么? load_breast_cancer().keys() 有什么作用?
- javascript - 如果两个 div 添加了一个类。所有的类都必须删除
- javascript - 如何使用注入令牌/App_init 概念使用 Angular 使用多个 url
- reactjs - React antd table reset search box input on button click
- java - 不兼容的类型:从 int 到字节错误的可能有损转换?
- logging - 禁用通话记录或短信权限的替代方案
- c++ - 如何修复'无法打开包含文件'boost/config.hpp':没有这样的文件或目录(包括目录封面:C:\Program Files\boost\boost_1_67_0)
- go - 返回嵌套结构的接口
- mongodb - 有没有办法对给定的 _id 数组执行多个 findById 操作?