Created
February 18, 2016 13:20
-
-
Save anula/fe81dd8fb6a41e62a91c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
global start | |
section .bss | |
stack_top: | |
resb 64 | |
stack_bottom: | |
section .text | |
bits 32 | |
start: | |
; initialize stack (growing downwards) | |
mov esp, stack_top | |
call check_multiboot | |
call check_cpuid | |
call check_long_mode | |
; print `OK` to screen | |
mov dword [0xb8000], 0x2f4b2f4f | |
hlt | |
; Prints `ERR: ` and the given error code to screen and hangs. | |
; parameter: error code (in ascii) in al | |
error: | |
mov dword [0xb8000], 0x4f524f45 | |
mov dword [0xb8004], 0x4f3a4f52 | |
mov dword [0xb8008], 0x4f204f20 | |
mov byte [0xb800a], al | |
hlt | |
; check if the kernel was actually loaded by multiboot | |
check_multiboot: | |
cmp eax, 0x36d76289 ; magic value that should be written by multiboot | |
jne .no_multiboot | |
ret | |
.no_multiboot: | |
mov al, "0" | |
jmp error | |
; check if CPUID is supported (copied from OSDev wiki) | |
check_cpuid: | |
; Check if CPUID is supported by attempting to flip the ID bit (bit 21) in | |
; the FLAGS register. If we can flip it, CPUID is available. | |
; Copy FLAGS in to EAX via stack | |
pushfd | |
pop eax | |
; Copy to ECX as well for comparing later on | |
mov ecx, eax | |
; Flip the ID bit | |
xor eax, 1 << 21 | |
; Copy EAX to FLAGS via the stack | |
push eax | |
popfd | |
; Copy FLAGS back to EAX (with the flipped bit if CPUID is supported) | |
pushfd | |
pop eax | |
; Restore FLAGS from the old version stored in ECX (i.e. flipping the ID bit | |
; back if it was ever flipped). | |
push ecx | |
popfd | |
; Compare EAX and ECX. If they are equal then that means the bit wasn't | |
; flipped, and CPUID isn't supported. | |
cmp eax, ecx | |
je .no_cpuid | |
ret | |
.no_cpuid: | |
mov al, "1" | |
jmp error | |
; check if long mode is supported | |
check_long_mode: | |
; test if extended processor info is available | |
mov eax, 0x80000000 ; implicit argument for cpuid | |
cpuid ; get highest supported argument | |
cmp eax, 0x80000001 ; it needs to be at least 0x80000001 | |
jb .no_long_mode ; if it's less, the CPU is too old for long mode | |
; use extended info to test if long mode is available | |
mov eax, 0x80000001 ; argument for extended processor info | |
cpuid ; returns various feature bits in ecx and edx | |
test edx, 1 << 29 ; test if the LM-bit is set in the D-register | |
jz .no_long_mode ; If it's not set, there is no long mode | |
ret | |
.no_long_mode: | |
mov al, "2" | |
jmp error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
global start | |
section .bss | |
stack_top: | |
resb 64 | |
stack_bottom: | |
section .text | |
bits 32 | |
start: | |
; initialize stack (growing downwards) | |
mov esp, stack_top | |
call check_multiboot | |
call check_cpuid | |
call check_long_mode | |
; print `OK` to screen | |
mov dword [0xb8000], 0x2f4b2f4f | |
hlt | |
; Prints `ERR: ` and the given error code to screen and hangs. | |
; parameter: error code (in ascii) in al | |
error: | |
mov dword [0xb8000], 0x4f524f45 | |
mov dword [0xb8004], 0x4f3a4f52 | |
mov dword [0xb8008], 0x4f204f20 | |
mov byte [0xb800a], al | |
hlt | |
my_error: | |
mov dword [0xb8000], 0x4f524f45 | |
mov dword [0xb8004], 0x4f3a4f52 | |
mov dword [0xb8008], 0x4f204f20 | |
mov byte [0xb800a], "2" | |
hlt | |
; check if the kernel was actually loaded by multiboot | |
check_multiboot: | |
cmp eax, 0x36d76289 ; magic value that should be written by multiboot | |
jne .no_multiboot | |
ret | |
.no_multiboot: | |
mov al, "0" | |
jmp error | |
; check if CPUID is supported (copied from OSDev wiki) | |
check_cpuid: | |
; Check if CPUID is supported by attempting to flip the ID bit (bit 21) in | |
; the FLAGS register. If we can flip it, CPUID is available. | |
; Copy FLAGS in to EAX via stack | |
pushfd | |
pop eax | |
; Copy to ECX as well for comparing later on | |
mov ecx, eax | |
; Flip the ID bit | |
xor eax, 1 << 21 | |
; Copy EAX to FLAGS via the stack | |
push eax | |
popfd | |
; Copy FLAGS back to EAX (with the flipped bit if CPUID is supported) | |
pushfd | |
pop eax | |
; Restore FLAGS from the old version stored in ECX (i.e. flipping the ID bit | |
; back if it was ever flipped). | |
push ecx | |
popfd | |
; Compare EAX and ECX. If they are equal then that means the bit wasn't | |
; flipped, and CPUID isn't supported. | |
cmp eax, ecx | |
je .no_cpuid | |
ret | |
.no_cpuid: | |
mov al, "1" | |
jmp error | |
; check if long mode is supported | |
check_long_mode: | |
; test if extended processor info is available | |
mov eax, 0x80000000 ; implicit argument for cpuid | |
cpuid ; get highest supported argument | |
cmp eax, 0x80000001 ; it needs to be at least 0x80000001 | |
jb .no_long_mode ; if it's less, the CPU is too old for long mode | |
; use extended info to test if long mode is available | |
mov eax, 0x80000001 ; argument for extended processor info | |
cpuid ; returns various feature bits in ecx and edx | |
test edx, 1 << 29 ; test if the LM-bit is set in the D-register | |
jz .no_long_mode ; If it's not set, there is no long mode | |
ret | |
.no_long_mode: | |
mov al, "2" | |
jmp error |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
thanks rlly helped me outbro