From c9f2bccb44c5437f1cae0862b2c84d3af47eade8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Duje=20Mihanovi=C4=87?= Date: Tue, 7 Sep 2021 11:25:40 +0200 Subject: [PATCH] A new beginning This boots into protected mode, prints a string from assembly and then prints an A from a minimal C kernel. --- .gitignore | 3 + Makefile | 34 +++++---- boot.s | 180 ++++++++++++++++++++++++++++++++---------------- kernel/entry.s | 5 ++ kernel/kernel.c | 5 ++ print.s | 136 ------------------------------------ 6 files changed, 156 insertions(+), 207 deletions(-) create mode 100644 kernel/entry.s create mode 100644 kernel/kernel.c delete mode 100644 print.s diff --git a/.gitignore b/.gitignore index 12ab2c1..735084c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ toolchain/ boot +boot.img +kernel/kernel.bin +kernel/*.o diff --git a/Makefile b/Makefile index 9d95b1e..7001c99 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,26 @@ -AS = yasm # choose yasm or nasm here -ASFLAGS = -f bin # compile a raw binary +AS = yasm +LD = i686-elf-ld +CC = i686-elf-gcc -boot: boot.s print.s - $(AS) $(ASFLAGS) -o $@ boot.s +all: boot.img -clean: - -rm boot +boot.img: boot kernel/kernel.bin + cat boot kernel/kernel.bin > $@ + truncate -s1440K $@ + +boot: boot.s + $(AS) -f bin boot.s -o $@ + +kernel/kernel.bin: kernel/entry.o kernel/kernel.o + $(LD) -o $@ -Ttext 0x1000 kernel/entry.o kernel/kernel.o --oformat=binary -run: - qemu-system-i386 boot +kernel/entry.o: kernel/entry.s + $(AS) -f elf kernel/entry.s -o $@ -help: - @echo "Run 'make' to compile." - @echo "Run 'make clean' to delete compiled objects." - @echo "Run 'make run' to run the compiled object. Must have qemu-system-i386 (but x86_64 should work too)." +kernel/kernel.o: kernel/kernel.c + $(CC) -o $@ -ffreestanding -c kernel/kernel.c + +clean: + rm boot kernel/kernel.bin kernel/entry.o kernel/kernel.o boot.img -.PHONY = clean run help +.PHONY: all clean diff --git a/boot.s b/boot.s index 51be5d9..a40b750 100644 --- a/boot.s +++ b/boot.s @@ -1,71 +1,135 @@ - bits 16 ; boot sectors run in real mode - org 7c00h ; boot sector is loaded at 0x7c00 + bits 16 + org 7C00h -_start - mov di, printing_numbers - call print +KERNEL_OFFSET equ 1000h - or bl, 1 - mov dx, 0DEADh ; number to print - call print_word + mov [BOOT_DRIVE], dl + + mov bp, 9000h + mov sp, bp + + mov di, 0 + + xor ax, ax + int 13h + jc reset_error + + mov ah, 2 + mov al, 10 + xor ch, ch + mov cl, 2 + xor dh, dh + xor bx, bx + mov es, bx + mov bx, KERNEL_OFFSET + int 13h + jc read_error + cmp al, 10 + jl read_error + jmp switch_to_pm + +reset_error + mov bx, 0B800h + mov es, bx + mov byte [es:di], '1' + jmp halt + +read_error + mov bx, 0B800h + mov es, bx + mov byte [es:di], '2' + jmp halt + + call switch_to_pm + +halt + jmp $ + +switch_to_pm + mov bx, 0B800h + mov es, bx + mov byte [es:0], 'L' + + cli + xor ax, ax + mov ds, ax + lgdt [gdt_desc] - mov di, space - call print + mov eax, cr0 + or eax, 1 + mov cr0, eax + jmp CODE_SEG:protected + + bits 32 +protected + mov ax, DATA_SEG + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax - xor bl, bl - mov dx, 0BEEFh - call print_word + mov ebp, 090000h + mov esp, ebp - mov di, waiting - call print + mov ebx, pm_success + call pmprint - mov di, keystroke - mov bl, 1 + call KERNEL_OFFSET -.loop - mov ah, 0 - int 16h - cmp ah, 1Ch - je .enterpressed - jmp .continue - cmp ah, 0Eh - je .backspace - jmp .continue -.enterpressed + jmp $ + +pmprint pusha - mov ah, 0Eh - mov al, 0Dh - int 10h - mov al, 0Ah - int 10h - popa + mov edx, video_memory + +.loop + mov al, [ebx] + mov ah, 0Fh + + cmp al, 0 + je .done + + mov [edx], al + mov [edx+1], ah + + inc ebx + add edx, 2 + jmp .loop -.backspace - pusha - mov ah, 03h - mov bh, 0 - int 10h - dec dl - mov ah, 02h - int 10h - mov ah, 0Eh - mov al, ' ' - int 10h - mov ah, 02h - int 10h + +.done popa - jmp .loop -.continue - mov [keystroke], al - call print - jmp .loop + ret + +pm_success db "Now in protected mode", 0 +video_memory equ 0B8000h -printing_numbers db "Printing some random hex numbers", 0 -waiting db "I await keystrokes", 0 -keystroke db "$", 0 -space db " ", 0 +gdt_start +null_seg + dq 0 +code_seg + dw 0FFFFh + dw 0 + db 0 + db 10011010b + db 11001111b + db 0 +data_seg + dw 0FFFFh + dw 0 + db 0 + db 10010010b + db 11001111b + db 0 +gdt_end +gdt_desc + dw gdt_end - gdt_start - 1 + dd gdt_start +CODE_SEG equ code_seg - gdt_start +DATA_SEG equ data_seg - gdt_start -%include "print.s" +BOOT_DRIVE db 0 - times 510-($-$$) db 0 ; fill with 0 until 0x1fc is reached - dw 0AA55h ; BIOS MBR signature + times 510-($-$$) db 0 + dw 0AA55h diff --git a/kernel/entry.s b/kernel/entry.s new file mode 100644 index 0000000..236b81e --- /dev/null +++ b/kernel/entry.s @@ -0,0 +1,5 @@ + bits 32 + extern _start + + call _start + jmp $ diff --git a/kernel/kernel.c b/kernel/kernel.c new file mode 100644 index 0000000..87fbef9 --- /dev/null +++ b/kernel/kernel.c @@ -0,0 +1,5 @@ +void _start(void) +{ + char *video_memory = (char *) 0xB8000; + *video_memory = 'A'; +} diff --git a/print.s b/print.s deleted file mode 100644 index 3a46c72..0000000 --- a/print.s +++ /dev/null @@ -1,136 +0,0 @@ -%define CURRENT_ADDR cs:di - -; Prints a null terminated string of your choice. -; Arguments: -; CS:DI - pointer to the string you want to print -; BL - 0 prints newline, otherwise no -print - pusha - mov ah, 0Eh ; teletype print -.write2 - mov al, [CURRENT_ADDR] ; get current char and put it in al - cmp al, 0 ; check if al is null (string terminator) - je .newline ; if it is, start a new line - int 10h ; otherwise write the char - inc di ; increment pointer to string - jmp .write2 ; jump back to this section -.newline - cmp bl, 1 - je .done - mov al, 0Dh ; carriage return - int 10h - mov al, 0Ah ; line feed - int 10h -.done - popa - ret ; return - -; Prints a word (16-bit value) in hex format. -; Arguments: -; DX - word to print -; BL - 0 will print a newline, 1 won't -print_word - pusha ; push all regs to stack - mov di, HEX_OUT+5 ; set destination index to last char in HEX_OUT - mov ax, dx ; copy argument to accumulator - and al, 00001111b ; extract the low nibble of the low half of the accumulator - call .compare ; fill in the string with correct value - dec di ; decrement string pointer - mov ax, dx ; copy argument to accumulator - and al, 11110000b ; extract high nibble of low half of accumulator - shr al, 4 ; shift high nibble to low nibble - call .compare ; fill in string with correct value - dec di - mov al, ah ; copy high portion of accumulator to low - and al, 00001111b ; - call .compare - dec di - mov al, ah - and al, 11110000b - shr al, 4 - call .compare - mov di, HEX_OUT - call print ; write string - popa - ret - -.compare - cmp al, 0 ; compare al with 0 - jne .one ; if not equal, compare with 1 - mov byte [CURRENT_ADDR], '0' ; set character to ASCII 0 - ret ; return -.one - cmp al, 1 - jne .two - mov byte [CURRENT_ADDR], '1' - ret -.two - cmp al, 2 - jne .three - mov byte [CURRENT_ADDR], '2' - ret -.three - cmp al, 3 - jne .four - mov byte [CURRENT_ADDR], '3' - ret -.four - cmp al, 4 - jne .five - mov byte [CURRENT_ADDR], '4' - ret -.five - cmp al, 5 - jne .six - mov byte [CURRENT_ADDR], '5' - ret -.six - cmp al, 6 - jne .seven - mov byte [CURRENT_ADDR], '6' - ret -.seven - cmp al, 7 - jne .eight - mov byte [CURRENT_ADDR], '7' - ret -.eight - cmp al, 8 - jne .nine - mov byte [CURRENT_ADDR], '8' - ret -.nine - cmp al, 9 - jne .ten - mov byte [CURRENT_ADDR], '9' - ret -.ten - cmp al, 0Ah - jne .eleven - mov byte [CURRENT_ADDR], 'A' - ret -.eleven - cmp al, 0Bh - jne .twelve - mov byte [CURRENT_ADDR], 'B' - ret -.twelve - cmp al, 0Ch - jne .thirteen - mov byte [CURRENT_ADDR], 'C' - ret -.thirteen - cmp al, 0Dh - jne .fourteen - mov byte [CURRENT_ADDR], 'D' - ret -.fourteen - cmp al, 0Eh - jne .fifteen - mov byte [CURRENT_ADDR], 'E' - ret -.fifteen - mov byte [CURRENT_ADDR], 'F' - ret - -HEX_OUT db "0x0000", 0 -- 2.39.2