use16
org 0x7C00

_start:
  cli            ; Disable ints.
  lgdt [gdtinfo] ; GDT crap, set Kernel to ring 0, full power
                 ; for user.
  mov  eax, cr0
  or   al, 1     ; Set PE bit
  mov  cr0, eax
  jmp  0x8:_GDT  ; Long jump to enable PE bit.

use32
_GDT:
  mov  ax, 16
  mov  ds, ax
  mov  es, ax
  mov  ss, ax
  mov  esp, 0x7C00

;===========================================================================;
; Micro Kernel start.                                                       ;
;===========================================================================;
Start:
  mov     dx, 3F2h      ; Move floppy disk port location into dx
  mov     al, 0         ; Clear AL
  out     dx, al        ; Turn off floppy disk
  mov     ah, 09        ; Blue
  mov     ESI, msg
  Call    PrintString
  mov     ah, 0B        ; CYAN!
  Call    Get_CPUID
  Mov     ESI, _CPUID
  Call    PrintString
  jmp   $

Get_CPUID:
   Push  EAX  ; Save regs we need to use later on.
   Push  ECX
   Push  EDX

   xor   eax, eax   ; get vendor ID
   cpuid          ; CPUID will now be saved into EBX, ECX, and EDX. So we need to
                  ; store that, should not be to hard. :-/
   Mov   ESI, _CPUID  ; This is were we store the CPU ID for now ;-)

   mov   DWORD [SI], EBX
   mov   DWORD [SI+4], ECX
   mov   DWORD [SI+8], EDX
; OK, so that is done! Lets restore what regs we saved and blow this joint!
   Pop   EDX
   Pop   ECX
   Pop   EAX
   ret
;================================;
; ESI = string to print          ;
;================================;
PrintString:
   lodsb                ; Get a byte from ESI and store it into AL.
   cmp   al, 0          ; Is the charecter 0?
   je    PSDone         ; If so our job here is done. :-)
   cmp   al, 13         ; Is the charecter enter?
   jne   Dexs_label
   call  go_down        ; go down a line ;-)
   jmp   PrintString    ; Do it again!
Dexs_label: 
   Call  PrintChar      ; Print the charecter to the screen.
   jmp   PrintString    ; Do it again!
 PSDone:
   ret                  ; Return to whome called us.  ^_^
;================================;
; Go down a line.                ;
;================================;
go_down:
   push eax             ; save eax's value.
   mov  [cur], byte 0   ; Return to the first colosion.
   mov  ah, [cur2]      ; Move row location into AH.
   cmp  ah, 24          ; Are we at maximum row?
   jb   new_line        ; if not, make a new line.
   jmp  GDDone          ; finish up here.
new_line:
   inc  ah              ; Increase line location.
   mov  [cur2], ah      ; Save the new location.
GDDone:
   pop  eax             ; Take back eax's value.
   ret                  ; We are SO done here.
;================================;
; AH = color                     ;
; AL = char to print             ;
;--------------------------------;
PrintChar:
   mov     ebx, 0       ; clear ebx
   mov     edi, 0xB8000 ; Move video memory start into edi
   mov     dh, [cur]    ; Move cursor position into bh.
   mov     dl, [cur2]   ; Move the row thaty the cursor needs to be printed in, into
                        ; BH so we can make many lines.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   push    eax   ; Coded by Dex/Dex4u
   movzx   bx, dl
   mov     ax, bx
   shl     ax, 5  ;4
   shl     bx, 7  ;6
   add     bx, ax
   movzx   ax, dh
   shl     ax, 1
   add     bx, ax
   pop     eax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   add     edi, ebx        ; Add cusor pos and video memory together to print in a
                           ; non-printed location.
   mov     [es:edi], ax    ; Move corsor pos, video location, font color, and char to
                           ; Print to the screen.
   cmp     [cur], 80       ; Are we at the end of the row? (80)
   je     PCDone           ; If so, wre done, dont increment the cursor.
   mov     bh, [cur]       ; Move cursor position into bh.
   inc     bh              ; move the cusor ahead, one space.
   mov     [cur], bh       ; Copy the last two bytes (cursor location) into the save spot.
PCDone:
   ret                     ; Return to were we were called from.
;===========================================================================;
; Data                                                                      ;
;===========================================================================;
cur  db 0 ; Cursor left to right. 2   = one space
cur2 db 0 ; Cursor up and down.   160 = one row
msg  db "CPUID: ",0

_CPUID db 0,0,0,0,0,0,0,0,0,0,0,0,0  ; I chose my favorate as default ;)

;==========================================-------------
gdt:
   dw    0x0000
   dw    0x0000
   dw    0x0000
   dw    0x0000
sys_code:
   dw    0xFFFF
   dw    0x0000
   dw    0x9800
   dw    0x00CF
sys_data:
   dw    0xFFFF
   dw    0x0000
   dw    0x9200
   dw    0x00CF
gdt_end:

gdtinfo:
   dw gdt_end - gdt - 1
   dd gdt
times 510- ($-$$)  db 0
dw 0xaa55
