《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
3.7 KiB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
  1. #include <asm.h>
  2. # Start the CPU: switch to 32-bit protected mode, jump into C.
  3. # The BIOS loads this code from the first sector of the hard disk into
  4. # memory at physical address 0x7c00 and starts executing in real mode
  5. # with %cs=0 %ip=7c00.
  6. .set PROT_MODE_CSEG, 0x8 # kernel code segment selector
  7. .set PROT_MODE_DSEG, 0x10 # kernel data segment selector
  8. .set CR0_PE_ON, 0x1 # protected mode enable flag
  9. # start address should be 0:7c00, in real mode, the beginning address of the running bootloader
  10. .globl start
  11. start:
  12. .code16 # Assemble for 16-bit mode
  13. cli # Disable interrupts
  14. cld # String operations increment
  15. # Set up the important data segment registers (DS, ES, SS).
  16. xorw %ax, %ax # Segment number zero
  17. movw %ax, %ds # -> Data Segment
  18. movw %ax, %es # -> Extra Segment
  19. movw %ax, %ss # -> Stack Segment
  20. # Enable A20:
  21. # For backwards compatibility with the earliest PCs, physical
  22. # address line 20 is tied low, so that addresses higher than
  23. # 1MB wrap around to zero by default. This code undoes this.
  24. seta20.1:
  25. inb $0x64, %al # Wait for not busy(8042 input buffer empty).
  26. testb $0x2, %al
  27. jnz seta20.1
  28. movb $0xd1, %al # 0xd1 -> port 0x64
  29. outb %al, $0x64 # 0xd1 means: write data to 8042's P2 port
  30. seta20.2:
  31. inb $0x64, %al # Wait for not busy(8042 input buffer empty).
  32. testb $0x2, %al
  33. jnz seta20.2
  34. movb $0xdf, %al # 0xdf -> port 0x60
  35. outb %al, $0x60 # 0xdf = 11011111, means set P2's A20 bit(the 1 bit) to 1
  36. # Switch from real to protected mode, using a bootstrap GDT
  37. # and segment translation that makes virtual addresses
  38. # identical to physical addresses, so that the
  39. # effective memory map does not change during the switch.
  40. lgdt gdtdesc
  41. movl %cr0, %eax
  42. orl $CR0_PE_ON, %eax
  43. movl %eax, %cr0
  44. # Jump to next instruction, but in 32-bit code segment.
  45. # Switches processor into 32-bit mode.
  46. ljmp $PROT_MODE_CSEG, $protcseg
  47. .code32 # Assemble for 32-bit mode
  48. protcseg:
  49. # Set up the protected-mode data segment registers
  50. movw $PROT_MODE_DSEG, %ax # Our data segment selector
  51. movw %ax, %ds # -> DS: Data Segment
  52. movw %ax, %es # -> ES: Extra Segment
  53. movw %ax, %fs # -> FS
  54. movw %ax, %gs # -> GS
  55. movw %ax, %ss # -> SS: Stack Segment
  56. # Set up the stack pointer and call into C. The stack region is from 0--start(0x7c00)
  57. movl $0x0, %ebp
  58. movl $start, %esp
  59. call bootmain
  60. # If bootmain returns (it shouldn't), loop.
  61. spin:
  62. jmp spin
  63. # Bootstrap GDT
  64. .p2align 2 # force 4 byte alignment
  65. gdt:
  66. SEG_NULLASM # null seg
  67. SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg for bootloader and kernel
  68. SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg for bootloader and kernel
  69. gdtdesc:
  70. .word 0x17 # sizeof(gdt) - 1
  71. .long gdt # address gdt