Skip to content

Instantly share code, notes, and snippets.

@Themaister
Created June 18, 2011 23:11
Show Gist options
  • Select an option

  • Save Themaister/1033579 to your computer and use it in GitHub Desktop.

Select an option

Save Themaister/1033579 to your computer and use it in GitHub Desktop.
section .text
; Yay, we start off in 16-bit. Time for our journey to reach long-mode 64-bit.
[bits 16]
org 7c00h
jmp 0:start
start:
; Check if we have 32-bit CPU.
xor ax, ax
mov ds, ax
mov eax, 80000000h
cpuid
cmp eax, 80000000h
jb no32
; Check if we have 64-bit CPU.
mov eax, 80000001h
cpuid
bt edx, 29
jnc no64
mov bx, success_str
call puts
; Enable address line or something.
in al, 092h
or al, 2
out 092h, al
; Set transfer target for floppy read. We read to [es:bx].
xor ax, ax
mov es, ax
mov bx, kernel_sector2
; int 13h floppy transfer.
mov ah, 02h
mov al, 03h
mov ch, 0
mov cl, 2
mov dh, 0
mov dl, 0
int 13h
jc fail
; Framebuffer mode :D
mov ax, 13h
int 10h
jmp 0:kernel_init
; DOS-style puts. :D
puts:
mov si, 0
mov ah, 0eh
puts_loop:
mov al, [bx + si]
cmp al, 0
je puts_end
int 10h
inc si
jmp puts_loop
puts_end:
ret
no32:
mov bx, no32_str
call puts
jmp $
no64:
mov bx, no64_str
call puts
jmp $
fail:
mov bx, fail_str
call puts
jmp $
no32_str: db "No 32-bit! :(", 0ah, 0dh, 00h
no64_str: db "No 64-bit! :(", 0ah, 0dh, 00h
success_str: db "Yay! :D", 0ah, 0dh, 00h
fail_str: db "Failed to load ...", 0ah, 0dh, 00h
# Pad
times 510 - ($-$$) db 0
db 55h
db 0aah
;Sector 2
; Here begins hell. I have no idea what's going on here.
kernel_sector2:
%macro system_segment_desc 3
dq ((%1 & 0ff000000h) << 20h) | ((%2 & 0ff0000h) << 20h) | (%3 << 20h) | ((%1 & 0ff0000h) << 10h) | ((%1 & 0ffffh) << 10h) | (%2 & 0ffffh)
dq %1 >> 20h
%endmacro
; o.O o.O o.O
%assign SEL_NULL 0
%assign SEL_CODE (1 << 3)
%assign SEL_LONG (2 << 3)
%assign SEL_DATA (3 << 3)
%assign SEL_USR_32b ((4 << 3) | 3)
%assign SEL_USR_DATA ((5 << 3) | 3)
%assign SEL_USR_LONG ((6 << 3) | 3)
%assign SEL_TSS (8 << 3)
%assign IDENT_MAP 0
%define TSS_LOC ($-$$ + 7c00h)
TSS:
TSS.ign1: dd 0 ; Ignorert
TSS.rsp0: dq 0 ; RSP for CPL=0
TSS.rsp1: dq 0 ; RSP for CPL=1
TSS.rsp2: dq 0 ; RSP for CPL=2
TSS.ign2: dq 0 ; Ignorert
TSS.ist1: dq 0
TSS.ist2: dq 0
TSS.ist3: dq 0
TSS.ist4: dq 0 ; Interrupt stack tabeller.
TSS.ist5: dq 0
TSS.ist6: dq 0
TSS.ist7: dq 0
TSS.ign3: dq 0 ; Ignorert
TSS.ign4: dw 0 ; Ignorert
TSS.iobase: dw 0 ; IO bitmap offset.
GDT:
.size dw 0ah * 8 - 1
.loc: dd .rGDT
dd 0
align 8
.rGDT:
.0: dq 0 ; Ubrukt
.1: dq 0000000011011111100110100000000000000000000000001111111111111111b
.2: dq 0000000000100000100110000000000000000000000000000000000000000000b
; ---------||-----||/|||---------------ignored-in-longmode--------
; || || ||`->Conforming
; |`Long || |`->Code/Data
; | || `->User
; | |`->CPL 0-3
; | `->Present
; `->If long, must be zero (default operand size)
.3: dq 0000000011011111100100100000000000000000000000001111111111111111b
; Usermode:
.4: dq 0
.5: dq 0000000000110000111100100000000000000000000000000000000000000000b
.6: dq 0000000000110000111111000000000000000000000000000000000000000000b
.7: dq 0
.8: system_segment_desc TSS_LOC + IDENT_MAP, 103, 8900h ; Takes 16 bytes
.A:
kernel_init:
jmp sanity
sanity:
lgdt [cs:GDT] ; Load in GDT, whatever that is :D
mov eax, cr0
bts eax, 0
mov cr0, eax
jmp far SEL_CODE:protmode
[bits 32]
%assign fb_ptr 0a0000h
; We're in 32-bit protected mode. Cool I guess?
protmode:
mov ax, SEL_DATA
mov ds, ax
mov es, ax
mov ss, ax
; Set up paging or something. Arbitrary address. Seems to work.
%assign PAGES 1000h
paging:
mov edi, PAGES
mov ecx, 1024
xor eax, eax
rep stosd
mov dword [PAGES ], PAGES + 1000h + 3
mov dword [PAGES + 1000h], PAGES + 2000h + 3
mov dword [PAGES + 2000h], 000000h + 83h
mov dword [PAGES + 2008h], 200000h + 83h
mov eax, PAGES
mov cr3, eax
; Long mode, yay?
set_longmode:
mov eax, cr4
bts eax, 5
mov cr4, eax
mov ecx, 0c0000080h
rdmsr
bts eax, 8
wrmsr
mov eax, cr0
bts eax, 31
mov cr0, eax
jmp far SEL_LONG:longmode
[bits 64]
longmode:
mov eax, 9fff8h
mov esp, eax
; o.O
mov [TSS.rsp0], rax
mov [TSS.rsp1], rax
mov [TSS.rsp2], rax
mov [TSS.ist1], rax
mov eax, SEL_TSS
ltr ax
call prog_main
jmp $
%assign screen_size (320 * 200)
clear_screen:
xor eax, eax
mov rbx, rdi
%rep 7
shl rdi, 8
or rbx, rdi
%endrep
clear_screen_loop:
mov [fb_ptr + eax], rbx
add rax, 8
cmp eax, screen_size
jne clear_screen_loop
ret
fill_screen:
xor eax, eax
xor ebx, ebx
fill_screen_loop:
mov [fb_ptr + eax + ebx], bl
inc ebx
cmp ebx, 256
jne line_change_skip
add eax, 320
xor ebx, ebx
line_change_skip:
cmp eax, screen_size
jne fill_screen_loop
ret
; Our "main" sort of.
prog_main:
mov di, 05h
call clear_screen
call fill_screen
ret
times 2048 - ($-$$) db 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment