2

I'm trying to make an OS WITHOUT GRUB. Now I wanna execute a C code from Protected Mode, but I don't know how.

I tried these commands (pm.bin is a compiled ASM code where I wanna call the C code and bootloader.bin is a first stage bootloader, it works correcly):

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

Okay, using the "cat" command I'll have binary C code after my binary ASM code, but how can I jump to the C code?

C code (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 (I need to call C from this file):

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

So how can I compile and link C and ASM code correctly and jump to the first one?

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 1
    You don't need to execute `dd` as root. Without seeing your code, it's hard to say what went wrong and as “nothing works” is not an error description, I don't even know what the symptoms are. – fuz Apr 20 '19 at 22:53
  • 2
    Please show us your entire `bootloader.asm` file and the code used to make `pm.bin` . One potential problem is the use of `-Ttext 0x0`. Unless you placed the code at 0x0000 in memory it won't run as expected. Also unclear why you placed pm.bin after kernel.bin. You really need to modify your question to be a [mcve] – Michael Petch Apr 20 '19 at 22:59
  • @Michael Petch, kernel.bin was supposed to be after pm.bin, just a typo – Гоша Обыночный Apr 21 '19 at 00:23
  • 1
    [How to make the kernel for my bootloader?](//stackoverflow.com/a/33619597) has a working example of a legacy BIOS real mode bootloader that calls a C kernel in 32-bit protected mode. Might be a useful starting point. – Peter Cordes Apr 21 '19 at 02:40
  • @Peter Cordes, thank you, it helped me to solve the problem! – Гоша Обыночный Apr 21 '19 at 09:05

0 Answers0