boot.s 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. .section .text.bootsect
  2. .code16
  3. # mbr
  4. .globl _start
  5. _start:
  6. jmp $0x07c0, $(real_start-_start)
  7. real_start:
  8. movw %cs, %ax
  9. movw %ax, %ds
  10. movw %ax, %es
  11. movw %ax, %ss
  12. # perform a temporary stack
  13. movw $(stack_base-_start), %ax
  14. movw %ax, %bp
  15. movw %ax, %sp
  16. call read_data
  17. ljmp $0x07e0, $(loader_start-loader_start)
  18. die:
  19. hlt
  20. jmp die
  21. read_data:
  22. movw $(read_data_pack-_start), %si
  23. mov $0x42, %ah
  24. mov $0x80, %dl
  25. int $0x13
  26. ret
  27. string_hello:
  28. .string "Hello World!"
  29. read_data_pack:
  30. .byte 0x10, 0
  31. .word 32 # block count (read 16k)
  32. .word 0x0000 # offset address
  33. .word 0x07e0 # segment address
  34. .long 1 # LBA to read
  35. stack_edge:
  36. .space 128
  37. stack_base:
  38. .section .text.loader
  39. # loader
  40. loader_start:
  41. # set segment registers
  42. movw %cs, %ax
  43. movw %ax, %ds
  44. _clear_screen:
  45. mov $0x00, %ah
  46. mov $0x03, %al
  47. int $0x10
  48. # get memory size info and storage it
  49. _get_memory_size:
  50. xorw %cx, %cx
  51. xorw %dx, %dx
  52. movw $0xe801, %ax
  53. int $0x15
  54. jc _get_memory_size_error
  55. cmpb $0x86, %ah # unsupported function
  56. je _get_memory_size_error
  57. cmpb $0x80, %ah # invalid command
  58. je _get_memory_size_error
  59. jcxz _get_memory_size_use_ax
  60. movw %cx, %ax
  61. movw %dx, %bx
  62. _get_memory_size_use_ax:
  63. movl $(asm_mem_size_info-loader_start), %edx
  64. movw %ax, (%edx)
  65. addw $2, %dx
  66. movw %bx, (%edx)
  67. jmp _e820_mem_map_load
  68. _get_memory_size_error:
  69. xchgw %bx, %bx
  70. jmp loader_halt
  71. _e820_mem_map_load:
  72. addl $4, %esp
  73. movl $0, (%esp)
  74. # save the destination address to es:di
  75. movw %cs, %ax
  76. movw %ax, %es
  77. movl $(asm_e820_mem_map-loader_start), %edi
  78. # clear ebx
  79. xorl %ebx, %ebx
  80. # set the magic number to edx
  81. movl $0x534D4150, %edx
  82. _e820_mem_map_load_loop:
  83. # set function number to eax
  84. movl $0xe820, %eax
  85. # set default entry size
  86. movl $24, %ecx
  87. int $0x15
  88. incl (%esp)
  89. addl %ecx, %edi
  90. jc _e820_mem_map_load_fin
  91. cmpl $0, %ebx
  92. jz _e820_mem_map_load_fin
  93. jmp _e820_mem_map_load_loop
  94. _e820_mem_map_load_fin:
  95. movl (%esp), %eax
  96. movl $(asm_e820_mem_map_count-loader_start), %edi
  97. movl %eax, (%edi)
  98. movl $(asm_e820_mem_map_entry_size-loader_start), %edi
  99. movl %ecx, (%edi)
  100. jmp _load_gdt
  101. _load_gdt:
  102. cli
  103. lgdt (asm_gdt_descriptor-loader_start)
  104. # enable protection enable (PE) bit
  105. movl %cr0, %eax
  106. orl $1, %eax
  107. movl %eax, %cr0
  108. ljmp $0x08, $0x7e00 + (start_32bit-loader_start)
  109. .code32
  110. start_32bit:
  111. movw $16, %ax
  112. movw %ax, %ds
  113. movw %ax, %es
  114. movw %ax, %fs
  115. movw %ax, %gs
  116. movw %ax, %ss
  117. # set up stack
  118. # in order to align 16 byte
  119. # set stack base address at
  120. # 0x003ffff0
  121. movl $0x03fffff0, %ebp
  122. movl $0x03fffff0, %esp
  123. call kernel_main
  124. loader_halt:
  125. hlt
  126. jmp loader_halt
  127. asm_gdt_descriptor:
  128. .word (5 * 8) - 1 # size
  129. .long 0x7e00+(asm_gdt_table-loader_start) # address
  130. .globl asm_gdt_descriptor
  131. .type asm_gdt_descriptor @object
  132. .size asm_gdt_descriptor, (.-asm_gdt_descriptor)
  133. asm_gdt_table:
  134. .8byte 0 # null descriptor
  135. # kernel code segment
  136. .word 0xffff # limit 0 :15
  137. .word 0x0000 # base 0 :15
  138. .byte 0x00 # base 16:23
  139. .byte 0x9a # access
  140. .byte 0b11001111 # flag and limit 16:20
  141. .byte 0x00 # base 24:31
  142. # kernel data segment
  143. .word 0xffff # limit 0 :15
  144. .word 0x0000 # base 0 :15
  145. .byte 0x00 # base 16:23
  146. .byte 0x92 # access
  147. .byte 0b11001111 # flag and limit 16:20
  148. .byte 0x00 # base 24:31
  149. # user code segment
  150. .word 0xffff # limit 0 :15
  151. .word 0x0000 # base 0 :15
  152. .byte 0x00 # base 16:23
  153. .byte 0xfa # access
  154. .byte 0b11001111 # flag and limit 16:20
  155. .byte 0x00 # base 24:31
  156. # kernel data segment
  157. .word 0xffff # limit 0 :15
  158. .word 0x0000 # base 0 :15
  159. .byte 0x00 # base 16:23
  160. .byte 0xf2 # access
  161. .byte 0b11001111 # flag and limit 16:20
  162. .byte 0x00 # base 24:31
  163. asm_mem_size_info:
  164. .word 0x12
  165. .word 0x34
  166. .globl asm_mem_size_info
  167. .type asm_mem_size_info @object
  168. .size asm_mem_size_info, (.-asm_mem_size_info)
  169. asm_e820_mem_map:
  170. .space 1024
  171. .globl asm_e820_mem_map
  172. .type asm_e820_mem_map @object
  173. .size asm_e820_mem_map, (.-asm_e820_mem_map)
  174. asm_e820_mem_map_count:
  175. .long 0
  176. .globl asm_e820_mem_map_count
  177. .type asm_e820_mem_map_count @object
  178. asm_e820_mem_map_entry_size:
  179. .long 0
  180. .globl asm_e820_mem_map_entry_size
  181. .type asm_e820_mem_map_entry_size @object