fork download
  1. [BITS 32]
  2. ;;
  3. ;; Multiboot header code
  4. ;;
  5. [SECTION .mbhdr]
  6. [EXTERN low_end]
  7. [EXTERN high_end]
  8. ALIGN 8
  9. MbHdr:
  10. dd 0xE85250D6 ;; MB2 Magic number
  11. dd 0 ;; Architecture
  12. dd HdrEnd - MbHdr ;; Length
  13. dd -(0xE85250D6 + HdrEnd - MbHdr) ;; Checksum
  14.  
  15. ;; Tags start here
  16.  
  17. ;; Set correct sections
  18. dw 2, 0
  19. dd 24
  20. dd MbHdr
  21. dd HdrEnd
  22. dd low_end
  23. dd high_end
  24.  
  25. ;; Set correct entry point
  26. dw 3, 0
  27. dd 12
  28. dd start
  29.  
  30. ;; Mark the end of the tags (see Multiboot specification)
  31. dw 0, 0
  32. dd 8
  33.  
  34. HdrEnd:
  35.  
  36.  
  37. ;;
  38. ;; Actual boot code
  39. ;;
  40. [SECTION .boot]
  41. [EXTERN Stack]
  42. [GLOBAL start]
  43. start:
  44. xchg bx, bx
  45. mov eax, GDT32Init ;; Get the GDT address
  46. lgdt [eax] ;; Load the GDT
  47. push 0x08 ;; Jump to
  48. push .GDT32works ;; code
  49. retf ;; segment
  50.  
  51. .GDT32works:
  52. mov eax, 0x10
  53. mov ds, ax ;; Set data and stack segment registers to
  54. mov ss, ax ;; the newly defined data segment
  55. mov esp, Stack ;; Set the Stack pointer to our reserved Stack
  56.  
  57. call EnableLongMode ;; Call the function that enables Long Mode
  58.  
  59. mov eax, GDT64Init ;; Now that we are in long mode, we need
  60. ;; a new GDT with 64 bit entries
  61. lgdt [eax] ;; Load the new GDT
  62. push 0x08 ;; Analogue to the previous stuff
  63. push .GDT64works
  64. retf
  65.  
  66. [BITS 64]
  67. [EXTERN kernel_main]
  68. .GDT64works:
  69. ;; xchg bx, bx
  70.  
  71. mov eax, 0x10 ;; Analogue to the previous stuff
  72. mov ds, ax
  73. mov es, ax
  74. mov ss, ax
  75.  
  76. ;; xchg bx, bx
  77. mov rsp, Stack + 0xFFFFFFFF80000000 ;; correct the stack pointer
  78.  
  79. mov rax, GDT64HigherHalfInit
  80. lgdt [rax]
  81.  
  82. xchg bx, bx
  83.  
  84. mov rax, qword kernel_main
  85. call rax
  86. cli
  87. jmp $
  88.  
  89. [BITS 32]
  90. [EXTERN PML4]
  91. [EXTERN PDPT]
  92. [EXTERN PD]
  93. EnableLongMode:
  94. mov eax, PDPT ;; Get the address of our page directory pointer table
  95. ;; This address is 4 kb aligned so the lower 12 bits
  96. ;; are free to contain flags
  97. or eax, 1 ;; Set the "present" flag of the address by
  98. ;; making sure, the lowest bit is 1
  99. mov [PML4], eax ;; Insert our newly created PDPT into the first
  100. ;; position of our PML4
  101. mov [PML4 + 0xFF8], eax ;; Insert it into the higher half part
  102. ;; as well, so we can access this part after enabling
  103. ;; the higher half part as well
  104. mov eax, PD ;; Get the address of our first page directory
  105. or eax, 1 ;; Set the present flag
  106. mov [PDPT], eax ;; Insert it into our PDPTs first position
  107. mov [PDPT + 0xFF0], eax ;; Insert it into the highest part as well
  108.  
  109. mov dword [PD], 0x000083 ;; Identity map the first pages and set
  110. mov dword [PD + 8], 0x200083 ;; their flags to "present", "read/write"
  111. mov dword [PD + 16], 0x400083 ;; and "global" (0x83 = 10000011)
  112. mov dword [PD + 24], 0x600083 ;;
  113.  
  114. mov eax, PML4 ;; Get the address of our root page directory
  115. mov cr3, eax ;; Insert it into the page directory register
  116.  
  117. mov eax, cr4 ;; Get content of the cr4 register
  118. or eax, 1 << 5 ;; Set the 5th flag of the cr4 content to
  119. ;; enable PAE
  120. mov cr4, eax ;; And reinsert into the cr4 register
  121.  
  122. mov ecx, 0xC0000080 ;; Specify which registers we want to read
  123. ;; The upper 32 bit go into EDX, the lower
  124. ;; ones into EAX
  125. rdmsr ;; Read the model specific registers
  126. or eax, 1 << 8 ;; Set the 8th bit to enable long mode
  127. wrmsr ;; Write back the data
  128.  
  129. mov eax, cr0 ;; Get the content of the cr0 register
  130. or eax, 1 << 31 ;; Set the 31st flag (paging enabled)
  131. mov cr0, eax ;; Reinsert the modified data
  132.  
  133. ret ;; Now that long mode is enabled, we jump
  134. ;; back to the calling function
  135.  
  136. ;;
  137. ;; Data structures we need for GDT and Paging setup
  138. ;;
  139.  
  140. GDT32Init:
  141. dw 23 ;; Number of bytes our gdt uses - 1
  142. dd GDT32 ;; Address of the GDT to load
  143.  
  144. GDT64Init:
  145. dw 23 ;; Number of bytes our gdt uses - 1
  146. dd GDT64 ;; Address of the GDT to load
  147. dd 0 ;; Empty the rest of the address to
  148. ;; stop remaining code remnants from
  149. ;; crapping our address
  150.  
  151. GDT64HigherHalfInit:
  152. dw 23 ;; Number of bytes our gdt uses - 1
  153. dq GDT64 + 0xFFFFFFFF80000000 ;; Translated address after
  154. ;; enabling paging
  155.  
  156. GDT32:
  157. dq 0x0000000000000000 ;; Null Segment
  158. dq 0x00CF9A000000FFFF ;; Code Segment
  159. dq 0x00CF92000000FFFF ;; Data Segment
  160.  
  161. GDT64:
  162. dq 0x0000000000000000 ;; Null Segment
  163. dq 0x00A09A0000000000 ;; Code Segment
  164. dq 0x00A0920000000000 ;; Data Segment
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty