Пытаюсь сделать ОС без 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" у меня будет двоичный код C после моего двоичного кода ASM, но как я могу перейти к коду C?
Код C (kernel.c):
void main() {
char* vga = (char*)0xb8000;
vga[0] = 'y';
vga[1] = 0x4;
}
bootloader.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 и перейти к первому?