global start section .text bits 32 start: mov esp, stack_top call check_multiboot call check_cpuid call check_long_mode ; print 'OK' mov dword [0xb8000], 0x2f4b2f4f hlt check_multiboot: cmp eax, 0x36d76289 jne .no_multiboot ret .no_multiboot mov al, "0" jmp error 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 EFLAGS in to EAX via stack pushfd pop eax ; Save the current flags mov ecx, eax ; Flip the ID bit xor eax, 1 << 21 ; push eax to eflags push eax popfd ; Copy EAX to FLAGS via the Stack 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 ; Check if the ID was changed cmp eax, ecx je .no_cpuid ret .no_cpuid: mov al, "1" jmp error check_long_mode: ; test if extended processor info in 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 ; extended info about long mode mov eax, 0x80000001 ; argument for the cpuid function cpuid ; Cpu id test edx, 1 << 29 ; check long mode availablity jz .no_long_mode ret .no_long_mode mov al, "2" jmp error ; Prints 'ERR: ' and the given error code to the screen and halts ; parameter: error code letter (ascii) in al error: mov dword [0xb8000], 0x4f524f45 mov dword [0xb8004], 0x4f3a4f52 mov dword [0xb8008], 0x4f504f20 mov byte [0xb800a], al hlt section .bss stack_bottom: resb 64 stack_top: