; Run in dos (not under windows) and it will take us to 32 bit protected mode

[ORG 0x100]         ; Reserve 256 bytes for dos


[BITS 16]           ; Dos is 16 bits


; assemble using 'nasm' assembler

; C:>nasm asm_2.asm -o test.exe

jmp entry           ; Jump to the start of our code

msg1 db 'Where good to go..$';

jumpOffset:
    dd go_pm
    dw 0x08

entry:
 
; Display a message showing where alive!

mov dx, msg1        ; register dx=msg1
mov ah, 9           ; register ah=9 -- the print string function
int 21h             ; dos service interrupt .. looks at register ah to figure out what to do

; Thanks from Brendan, as we have to make sure our GDTR points to the actual
; memory address, add 0x100 onto our loaded offset 

    mov eax,0
    mov ax,cs
    shl eax,4
    add [gdtr+2],eax
    add [jumpOffset],eax


  cli		    ; Clear or disable interrupts
  lgdt[gdtr]	    ; Load GDT
  mov eax,cr0	    ; The lsb of cr0 is the protected mode bit
  or al,0x01	    ; Set protected mode bit
  mov cr0,eax	    ; Mov modified word to the control register
  

jmp far dword [jumpOffset]  ;can't just use "jmp go_pm" as where in dos!


nop                 ; ignore - no operation opcodes :)
nop

; Once we reach here where in protected mode!  32 Bit!  Where not in
; the real world (mode) anymore :)
[BITS 32]
go_pm :

mov ax, 0x10        ; use our datasel selector ( alternatively mov ax, datasel )
mov ds, ax,
mov es, ax

mov word [es: 0xb8000],0x740 ; put a char to the screen!...yeahh!


lp: jmp lp  ; loops here forever and ever...


; We use 16 bits here - as you'll notice we use dw and dd only,
; and out data will be packed together nice and tight.

[BITS 16]

align 4


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Our GDTR register value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

gdtr :
   dw gdt_end-gdt-1    ; Length of the gdt
   dd gdt	       ; physical address of gdt

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This is the start of our gdt - its actual value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

align 4

gdt:
nullsel equ $-gdt      ; $->current location,so nullsel = 0h
gdt0 		       ; Null descriptor,as per convention gdt0 is 0
   dd 0		       ; Each gdt entry is 8 bytes, so at 08h it is CS
   dd 0                ; In all the segment descriptor is 64 bits
codesel: ; equ $-gdt      ; This is 8h,ie 2nd descriptor in gdt
code_gdt:	       ; Code descriptor 4Gb flat segment at 0000:0000h
   dw 0x0ffff	       ; Limit 4Gb  bits 0-15 of segment descriptor
   dw 0x0000	       ; Base 0h bits 16-31 of segment descriptor (sd)
   db 0x00             ; Base addr of seg 16-23 of 32bit addr,32-39 of sd	
   db 0x09a	       ; P,DPL(2),S,TYPE(3),A->Present bit 1,Descriptor	
                       ; privilege level 0-3,Segment descriptor 1 ie code	    		                  
                       ; or data seg descriptor,Type of seg,Accessed bit
   db 0x0cf	       ; Upper 4 bits G,D,0,AVL ->1 segment len is page		                                     
                       ; granular, 1 default operation size is 32bit seg		                              
                       ; AVL : Available field for user or OS
                       ; Lower nibble bits 16-19 of segment limit
   db 0x00	       ; Base addr of seg 24-31 of 32bit addr,56-63 of sd
datasel: ; equ $-gdt      ; ie 10h, beginning of next 8 bytes for data sd
data_gdt:	       ; Data descriptor 4Gb flat seg at 0000:0000h
   dw 0x0ffff	       ; Limit 4Gb
   dw 0x0000	       ; Base 0000:0000h
   db 0x00	       ; Descriptor format same as above
   db 0x092
   db 0x0cf
   db 0x00

gdt_end:



TIMES 0x500-($-$$) DB 0x90    ; And of course, this will make our file size
                             ; equal to 0x500 a nice round number -
                             ; 0x500 ... so if you assemble the file
                             ; you should find its that size exactly.



