Advertisement
MichaelPetch

boot.s

Sep 3rd, 2019
423
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.87 KB | None | 0 0
  1. /* Enable intel syntax */
  2. .intel_syntax noprefix
  3. /* Declare constants for the multiboot header. */
  4. .set ALIGN, 1<<0 /* align loaded modules on page boundaries */
  5. .set MEMINFO, 1<<1 /* provide memory map */
  6. .set FLAGS, ALIGN | MEMINFO /* this is the Multiboot 'flag' field */
  7. .set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */
  8. .set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */
  9.  
  10. /*
  11. Declare a multiboot header that marks the program as a kernel. These are magic
  12. values that are documented in the multiboot standard. The bootloader will
  13. search for this signature in the first 8 KiB of the kernel file, aligned at a
  14. 32-bit boundary. The signature is in its own section so the header can be
  15. forced to be within the first 8 KiB of the kernel file.
  16. */
  17. .section .multiboot
  18. .align 4
  19. .long MAGIC
  20. .long FLAGS
  21. .long CHECKSUM
  22.  
  23. .section .data
  24. /*
  25. GDT from the old DripOS bootloader, which was from the original
  26. project (The OS tutorial)
  27. */
  28.  
  29. gdt_start:
  30.  
  31. .long 0x0
  32. .long 0x0
  33.  
  34. gdt_code:
  35. .word 0xffff
  36. .word 0x0
  37. .byte 0x0
  38. .byte 0x9A /*10011010 in binary*/
  39. .byte 0xCF /*11001111 in binary*/
  40. .byte 0x0
  41. gdt_data:
  42. .word 0xffff
  43. .word 0x0
  44. .byte 0x0
  45. .byte 0x92 /*10010010 in binary*/
  46. .byte 0xCF /*11001111 in binary*/
  47. .byte 0x0
  48.  
  49. gdt_end:
  50.  
  51. gdt_descriptor:
  52. .word gdt_end - gdt_start - 1
  53. .long gdt_start
  54.  
  55. CODE_SEG = gdt_code - gdt_start
  56. DATA_SEG = gdt_data - gdt_start
  57.  
  58. /*
  59. The multiboot standard does not define the value of the stack pointer register
  60. (esp) and it is up to the kernel to provide a stack. This allocates room for a
  61. small stack by creating a symbol at the bottom of it, then allocating 16384
  62. bytes for it, and finally creating a symbol at the top. The stack grows
  63. downwards on x86. The stack is in its own section so it can be marked nobits,
  64. which means the kernel file is smaller because it does not contain an
  65. uninitialized stack. The stack on x86 must be 16-byte aligned according to the
  66. System V ABI standard and de-facto extensions. The compiler will assume the
  67. stack is properly aligned and failure to align the stack will result in
  68. undefined behavior.
  69. */
  70. .section .bss
  71. .align 16
  72. stack_bottom:
  73. .skip 16384 # 16 KiB
  74. stack_top:
  75.  
  76. /*
  77. The linker script specifies _start as the entry point to the kernel and the
  78. bootloader will jump to this position once the kernel has been loaded. It
  79. doesn't make sense to return from this function as the bootloader is gone.
  80. */
  81. .section .text
  82. .global _start
  83. .type _start, @function
  84. _start:
  85. /*
  86. The bootloader has loaded us into 32-bit protected mode on a x86
  87. machine. Interrupts are disabled. Paging is disabled. The processor
  88. state is as defined in the multiboot standard. The kernel has full
  89. control of the CPU. The kernel can only make use of hardware features
  90. and any code it provides as part of itself. There's no printf
  91. function, unless the kernel provides its own <stdio.h> header and a
  92. printf implementation. There are no security restrictions, no
  93. safeguards, no debugging mechanisms, only what the kernel provides
  94. itself. It has absolute and complete power over the
  95. machine.
  96. */
  97.  
  98. /*
  99. To set up a stack, we set the esp register to point to the top of the
  100. stack (as it grows downwards on x86 systems). This is necessarily done
  101. in assembly as languages such as C cannot function without a stack.
  102. */
  103. mov stack_top, esp
  104.  
  105. /*
  106. This is a good place to initialize crucial processor state before the
  107. high-level kernel is entered. It's best to minimize the early
  108. environment where crucial features are offline. Note that the
  109. processor is not fully initialized yet: Features such as floating
  110. point instructions and instruction set extensions are not initialized
  111. yet. The GDT should be loaded here. Paging should be enabled here.
  112. C++ features such as global constructors and exceptions will require
  113. runtime support to work as well.
  114. */
  115. lgdt [gdt_descriptor] /* Load the GDT */
  116. /*
  117. Enter the high-level kernel. The ABI requires the stack is 16-byte
  118. aligned at the time of the call instruction (which afterwards pushes
  119. the return pointer of size 4 bytes). The stack was originally 16-byte
  120. aligned above and we've since pushed a multiple of 16 bytes to the
  121. stack since (pushed 0 bytes so far) and the alignment is thus
  122. preserved and the call is well defined.
  123. */
  124. mov ax, DATA_SEG
  125. mov ds, ax
  126. mov es, ax
  127. mov fs, ax
  128. mov gs, ax
  129. jmp CODE_SEG:.next /* JMP to next instruction but set CS! */
  130. .next:
  131.  
  132. mov ebp, 0x90000
  133. mov esp, ebp
  134. call main
  135.  
  136. /*
  137. If the system has nothing more to do, put the computer into an
  138. infinite loop. To do that:
  139. 1) Disable interrupts with cli (clear interrupt enable in eflags).
  140. They are already disabled by the bootloader, so this is not needed.
  141. Mind that you might later enable interrupts and return from
  142. kernel_main (which is sort of nonsensical to do).
  143. 2) Wait for the next interrupt to arrive with hlt (halt instruction).
  144. Since they are disabled, this will lock up the computer.
  145. 3) Jump to the hlt instruction if it ever wakes up due to a
  146. non-maskable interrupt occurring or due to system management mode.
  147. */
  148. cli
  149. 1: hlt
  150. jmp 1b
  151.  
  152. /*
  153. Set the size of the _start symbol to the current location '.' minus its start.
  154. This is useful when debugging or when you implement call tracing.
  155. */
  156. .size _start, . - _start
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement