簡體   English   中英

內核開發中的匯編和C

[英]Kernel Dev In assembly & C

我試圖使用bochs在Linux上使用匯編和C語言創建一個簡單的內核。 每次我嘗試從匯編代碼調用c代碼時,模擬器都會給我一個錯誤,並重置仿真。 當我以16位實模式啟動時,我使用此代碼

global _start

[bits 16]

_start:

mov [BOOT_DRIVE] , dl

mov bp , 0x7000
mov sp , bp

mov bx , 0x0000 ;load 5 sectors to 0x0000(ES):0x9000(BX)
mov es , bx
mov bx , KERNEL_OFFSET
mov dh , 15
mov dl , [BOOT_DRIVE]
call disk_load

mov dx , [es:KERNEL_OFFSET]
call print_hex

call switch_to_pm

jmp $

切換到保護模式后,這是代碼

[bits 32]
extern kmain

begin_pm:

;print a char to vram for testing and it is printed, this means the switch has suceeded
mov ebx , VRAM_ADDRESS
mov al , 'H'
mov [ebx] , al
mov al , 0x07
inc ebx
mov [ebx] , al

call kmain

jmp $

C函數基本上什么也不做,只是一個空的

關於我正在使用的命令

nasm $asm_file_name.asm -f elf -o $asm_file_name.o
gcc -ffreestanding -c $c_file_name.c -o $c_file_name.o
ld -o $c_file_name.bin -Ttext 0x7c00 $asm_file_name.o $c_file_name.o --oformat binary
dd status=noxfer conv=notrunc if=$c_file_name.bin of=$floppy_name.img

我不在哪里。 有任何想法嗎 ?

注意:我正在使用以下GDT和switch_to_pm函數

    ;GDT
gdt_start:

    gdt_null:
        dd 0x0
        dd 0x0

    gdt_code: ;the code segment descriptor
        ; base = 0x0 , limit = 0xfffff ,
        ; 1 st flags : ( present )1 ( privilege )00 ( descriptor type )1 -> 1001 b
        ; type flags : ( code )1 ( conforming )0 ( readable )1 ( accessed )0 -> 1010 b
        ; 2 nd flags : ( granularity )1 (32 - bit default )1 (64 - bit seg )0 ( AVL )0 -> 1100 b
        dw 0xffff
        ; Limit (bits 0 -15)
        dw 0x0
        ; Base (bits 0 -15)
        db 0x0
        ; Base ( bits 16 -23)
        db 10011010b ; 1st flags , type flags
        db 11001111b ; 2nd flags , Limit (bits 16 -19)
        db 0x0
        ; Base ( bits 24 -31)

    gdt_data: ; the data segment descriptor
        ; Same as code segment except for the type flags :
        ; type flags : ( code )0 ( expand down )0 ( writable )1 ( accessed )0 -> 0010 b
        dw 0xffff
        ; Limit ( bits 0 -15)
        dw 0x0
        ; Base ( bits 0 -15)
        db 0x0
        ; Base ( bits 16 -23)
        db 10010010b ; 1 st flags , type flags
        db 11001111b ; 2 nd flags , Limit ( bits 16 -19)
        db 0x0
        ; Base ( bits 24 -31)

    gdt_end:
    ; The reason for putting a label at the end of the
    ; GDT is so we can have the assembler calculate
    ; the size of the GDT for the GDT decriptor ( below )
    ; GDT descriptior
    gdt_descriptor:
        dw gdt_end - gdt_start - 1
        dd gdt_start

    ; Size of our GDT , always less one
    ; of the true size
    ; Start address of our GDT
    ; Define some handy constants for the GDT segment descriptor offsets , which
    ; are what segment registers must contain when in protected mode. For example ,
    ; when we set DS = 0 x10 in PM , the CPU knows that we mean it to use the
    ; segment described at offset 0 x10 ( i.e. 16 bytes ) in our GDT , which in our
    ; case is the DATA segment (0 x0 -> NULL ; 0 x08 -> CODE ; 0 x10 -> DATA )
    CODE_SEG equ gdt_code - gdt_start
    DATA_SEG equ gdt_data - gdt_start
[bits 16]

switch_to_pm:

cli
lgdt[gdt_descriptor]

mov eax , cr0
or eax , 0x1
mov cr0 , eax

jmp CODE_SEG:init_pm

[bits 32]

init_pm:

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

mov ebp , 0x9000
mov esp , ebp

jmp begin_pm

call kmain會嘗試在該地址處查找該函數,就像整個代碼已加載到0x7c00一樣。 但是,整個代碼將從磁盤加載到0x9000中。 因此,您需要讓鏈接程序修復它用作kmain的地址的地址。

甚至更好,如@AlexeyFrunze所建議的那樣,在BIOS加載第一個扇區之后,將第二個扇區開始的代碼直接加載到內存中的位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM