hello.S 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /* hello.S -- Hello, World on bare metal, just after BIOS boot. x86 */
  2. .file "hello.S"
  3. /*
  4. * A couple of constants.
  5. *
  6. * These can't be changed, because they are set by the
  7. * firmware (BIOS).
  8. */
  9. .set LOAD, 0x7c00 # BIOS loads and jumps here
  10. .set MAGIC, 0xaa55 # Must be at the end of the 512-byte block
  11. .set BLOCKSIZE, 512 # Boot block is BLOCKSIZE bytes long
  12. /*
  13. * The .text section contains the opcodes (code) for our
  14. * program.
  15. */
  16. .section .text # This is a code (text) section.
  17. .code16 # Boot code runs in 16-bit real mode
  18. .globl start # Entry point is public, for the linker.
  19. start:
  20. /*
  21. * The processor starts in real mode and executes the first
  22. * instruction at address $0xFFFF:FFF0. System designers
  23. * usually map BIOS at this address, so the CPU starts running
  24. * BIOS code. The BIOS initializes RAM and other components.
  25. * Then, it loads $BLOCKSIZE bytes from the first boot device
  26. * in RAM, starting at address $0x0:$LOAD.
  27. *
  28. * If that block finishes with the $MAGIC sequence 0x55, 0xaa
  29. * (it is reversed, because IA-32 arch is little endian), BIOS
  30. * considers this block a valid boot block, and jumps right here.
  31. */
  32. /*
  33. * Initialize segment descriptors %ds, %es, and %ss to 0x0.
  34. * %cs:%ip is already set by the BIOS to 0x0:$LOAD.
  35. */
  36. xorw %ax, %ax
  37. movw %ax, %es
  38. movw %ax, %ds
  39. /*
  40. * Initialize the stack.
  41. *
  42. * Since the stack on x86 grows towards *lower* addresses,
  43. * we anchor it at $LOAD. Note that we don't collide with
  44. * the code because the stack will always remain below
  45. * (i.e. less than) $LOAD and grows downwards from there.
  46. * disable intterupts when setting up the stack. If an
  47. * interrupt occurs between the two MOVs then the stack
  48. * may point at the wrong memory location and the interrupt
  49. * may crash the system
  50. */
  51. cli
  52. movw %ax, %ss
  53. movw $LOAD, %sp
  54. sti
  55. /*
  56. * This is the "main" program:
  57. *
  58. * Clear screen, move cursor to the top:left,
  59. * and display a friendly greetings.
  60. */
  61. callw clrscr # clear screen
  62. callw curshome # move cursor home - top:left
  63. callw greeting # display a greeting string
  64. /*
  65. * That's all, folks!
  66. *
  67. * We could run a tight loop here, but it's better to halt
  68. * the processor. When run on bare metal, a halted processor
  69. * consumes less power (especially useful if ran on battery).
  70. * When run under an emulator, the emulator doesn't consume
  71. * further CPU cycles. Turn off interrupts before caling HLT
  72. * because execution will only HLT until the next intterupt
  73. * occurs. Once an interrupt occurs execution continues at
  74. * the next instruction after HLT
  75. */
  76. cli
  77. hlt
  78. /* greeting() -- display a little message. */
  79. greeting:
  80. /*
  81. * greeting dislays the string located at label msg,
  82. * using the convenience function puts() defined below.
  83. * We pass the *address* of that string (thus $msg instead
  84. * of msg) in the %si register.
  85. */
  86. movw $msg, %si
  87. callw puts
  88. retw
  89. /*
  90. * Finally, include the BIOS convenience functions used above.
  91. */
  92. .include "biosfunc.S" # BIOS convenience functions.
  93. .file "hello.S"
  94. /* msg: the string buffer to be displayed. */
  95. msg:
  96. .asciz "Hello, World!\r\n" # must be \0-terminated!
  97. /*
  98. * The boot block MUST end with a MAGIC sequence.
  99. *
  100. * The BIOS checks this, and would refuse to boot unless
  101. * MAGIC is there. The last two bytes of the BLOCKSIZE
  102. * long block must contain the magic sequence 0x55, 0xaa.
  103. * We move the assembler pointer .org there, and emit the
  104. * word MAGIC. Note that MAGIC is set to 0xaa55, and not
  105. * 0x55aa, because the IA-32 platform is little endian.
  106. */
  107. .org BLOCKSIZE - 2
  108. .word MAGIC