kernel/kernel.asm

Code:
  1. ;By Marcus Xing   
  2. ;/kernel/kernel.asm   
  3. ;内核的入口,以及进行后续的一系列工作   
  4.   
  5. ;----------------------------------------------------------------------------EQU   
  6. Selector_Kernel_Flat_RW     equ 8           ;内核中GDT的FLAT_RW段选择子   
  7. Selector_Kernel_Flat_C      equ 16          ;内核中GDT的FLAT_C段选择子   
  8. Selector_TSS                equ 32          ;TSS的选择子   
  9. Selector_Kernel_Flat_C_16   equ 126 * 8     ;内核中GDT中的FLAT的16位段的选择子   
  10. Selector_Normal             equ 127 * 8     ;Normal描述符的选择子   
  11. LDT_Sel_Offset_Of_PCB       equ 72          ;PCB中LDT选择子在PCB的偏移   
  12. Stack_Frame_Top             equ 72          ;PCB的寄存器的最高地址,从进程切换到中断处理   
  13.                                             ;程序时候esp应该指向[p_Next_PCB + Stack_Frame_Top]   
  14.                                                                        
  15. Save_Ret_Addr_Offset        equ 48          ;Save函数的返回地址在PCB的偏移   
  16. EAX_Offset                  equ 44          ;EAX寄存器在PCB的偏移   
  17. EOI                                         equ 20h    
  18. TSS_ESP0_OFFSET             equ 4           ;TSS结构ESP0字段的偏移   
  19.   
  20. ;-------------------------------------------------------------------------GLOBAL   
  21. global _start       ;默认入口点   
  22.   
  23. ;内中断处理函数导出   
  24. global Divide_Error   
  25. global Single_Step_Exception   
  26. global NMI   
  27. global Breakpoint_Exception   
  28. global Overflow   
  29. global Bounds_Check   
  30. global Inval_Opcode   
  31. global Copr_Not_Available   
  32. global Double_Fault   
  33. global Copr_Seg_Overrun   
  34. global Inval_TSS   
  35. global Segment_Not_Present   
  36. global Stack_Exception   
  37. global General_Protection   
  38. global Page_Fault   
  39. global Copr_Error   
  40.   
  41. ;外中断处理函数导出   
  42. global hw_00   
  43. global hw_01   
  44. global hw_02   
  45. global hw_03   
  46. global hw_04   
  47. global hw_05   
  48. global hw_06   
  49. global hw_07   
  50. global hw_08   
  51. global hw_09   
  52. global hw_10   
  53. global hw_11   
  54. global hw_12   
  55. global hw_13   
  56. global hw_14   
  57. global hw_15   
  58.   
  59. ;系统调用导出   
  60. global System_Call   
  61. global Prepare_To_Real_Mode   
  62.   
  63. ;-------------------------------------------------------------------------EXTERN   
  64. ;各函数和变量的详细解释见include/proto.h和include/global.h   
  65. ;FUNCTION   
  66. extern  Init_GDT   
  67. extern  Init_IDT   
  68. extern  GDT_Ptr   
  69. extern  IDT_Ptr   
  70. extern  Init_8259A   
  71. extern  Init_TSS   
  72. extern  Init_PCB   
  73. extern  Exception_Handler   
  74. extern  Hard_Int_Handler   
  75. extern  Disp_Str   
  76. extern  Delay   
  77. extern  Enable_IRQ   
  78. extern  Disable_IRQ   
  79. extern  Init_8253   
  80. extern  Init_Clock   
  81. extern  Init_Keyboard   
  82. extern  Init_All_TTY   
  83. extern  Memory_Copy   
  84.   
  85. ;VARIABLE   
  86. extern  d_Disp_Pos   
  87. extern  p_Next_PCB   
  88. extern  tss   
  89. extern  d_Flag_Reenter   
  90. extern  IRQ_Handler_Table   
  91. extern  System_Call_Handler_Table   
  92.   
  93. ;-------------------------------------------------------------------CODE_SEGMENT   
  94. [section .text]   
  95. [bits 32]              
  96.   
  97. _start:    
  98.     pop dword [d_Disp_Pos]          ;把LOADER中的显示位置赋给KERNEL中的相应变量   
  99.   
  100.     ;保存实模式下的IDTR和IMR的值   
  101.     sidt    [b6_Old_IDTR_Value]   
  102.     in  al,21h   
  103.     mov byte [b_Old_IMR],al   
  104.        
  105.     ;复制保存下来的值到0:8000处   
  106.     push    Data_Len   
  107.     push    LABEL_DATA   
  108.     push    0x8000   
  109.     call    Memory_Copy   
  110.     add esp,12   
  111.        
  112.     ;复制1M下的实模式代码到0:9000h处   
  113.     push    Code16_Len   
  114.     push    LABEL_ALREADY_REAL_MODE   
  115.     push    0x9000   
  116.     call    Memory_Copy   
  117.     add esp,12   
  118.   
  119.     ;此时ds,es,fs,ss所指向的描述符还在LOADER,即GDT还在LOADER空间中   
  120.     call    Init_GDT                    ;初始化GDT,但尚未切换   
  121.     call    Init_8259A                  ;初始化8259a   
  122.     call    Init_IDT                    ;初始化IDT,但尚未切换   
  123.        
  124.     ;此时GDT已经移动到内核中,内容和LOADER中的GDT是一样的,所以选择子和一样   
  125.     lgdt    [GDT_Ptr]                   ;加载入GDTR   
  126.     lidt    [IDT_Ptr]                   ;加载入IDTR   
  127.        
  128.     ;使用设置在内核的FLAT_C段   
  129.     jmp Selector_Kernel_Flat_C:_GO_ON   
  130.   
  131. _GO_ON:   
  132.        
  133.     mov esp,Top_Of_Kernel_Stack ;堆栈顶指针也移动到内核空间中   
  134.     call    Init_TSS                    ;初始化TSS   
  135.     call    Init_PCB                    ;初始化PCB   
  136.     call    Init_8253                   ;初始化8253   
  137.     call    Init_Clock                  ;初始化时钟中断   
  138.     call    Init_Keyboard               ;初始化键盘中断   
  139.     call    Init_All_TTY                ;初始化所有的TTY   
  140.        
  141.     ;加载入tr   
  142.     mov ax,Selector_TSS            
  143.     ltr ax   
  144.        
  145.     jmp     Restart                     ;准备进入第一个进程   
  146.        
  147. Restart:   
  148.     mov esp,[p_Next_PCB]                ;令esp指向将要执行的进程的PCB最低位置处,   
  149.                                         ;准备把PCB中的数据弹出   
  150.     ;加载进程的LDT选择子入ldtr                                                          
  151.     lldt    [esp + LDT_Sel_Offset_Of_PCB]   
  152.        
  153.     ;设置TSS的ESP0字段为当前进程PCB的寄存器栈的最高地址   
  154.     lea eax,[esp + Stack_Frame_Top]   
  155.     mov [tss + TSS_ESP0_OFFSET],eax   
  156.        
  157.     ;重入进入,不切换进程   
  158. Reenter:   
  159.     dec dword [d_Flag_Reenter]  ;重入标志变量自减1   
  160.     ;当前进程的PCB的各寄存值POP出去   
  161.     pop fs   
  162.     pop gs   
  163.     pop es   
  164.     pop ds   
  165.     popad   
  166.        
  167.     add esp,4       ;跳过save_ret_addr   
  168.        
  169.     ;正式进入第一个进程   
  170.     iretd   
  171.   
  172. ;-------------------------------------------------------------INNER_INT_HANDLERS   
  173. ;有些内中断有错误码,有些没有,没有的就压入   
  174. ;0ffffffffh值来代替,以此保持一致   
  175. Divide_Error:   
  176.     push 0ffffffffh   
  177.     push 0   
  178.     jmp Exception   
  179. Single_Step_Exception:   
  180.     push 0ffffffffh   
  181.     push 1   
  182.     jmp Exception   
  183. NMI:   
  184.     push 0ffffffffh   
  185.     push 2   
  186.     jmp Exception   
  187. Breakpoint_Exception:   
  188.     push 0ffffffffh   
  189.     push 3   
  190.     jmp Exception   
  191. Overflow:   
  192.     push 0ffffffffh   
  193.     push 4   
  194.     jmp Exception   
  195. Bounds_Check:   
  196.     push 0ffffffffh   
  197.     push 5   
  198.     jmp Exception   
  199. Inval_Opcode:   
  200.     push 0ffffffffh   
  201.     push 6   
  202.     jmp Exception   
  203. Copr_Not_Available:   
  204.     push 0ffffffffh   
  205.     push 7   
  206.     jmp Exception   
  207. Double_Fault:   
  208.     push 8   
  209.     jmp Exception   
  210. Copr_Seg_Overrun:   
  211.     push 0ffffffffh   
  212.     push 9   
  213.     jmp Exception   
  214. Inval_TSS:   
  215.     push 10   
  216.      jmp Exception   
  217. Segment_Not_Present:   
  218.     push 11   
  219.     jmp Exception   
  220. Stack_Exception:   
  221.     push 12   
  222.     jmp Exception   
  223. General_Protection:   
  224.     push 13   
  225.     jmp Exception   
  226. Page_Fault:   
  227.     push 14   
  228.     jmp Exception   
  229. Copr_Error:   
  230.     push 0ffffffffh   
  231.     push 16   
  232.     jmp Exception   
  233. Exception:   
  234. ;此时堆栈先后压入了eflags,cs,eip,error_code,int_vector   
  235.     call Exception_Handler  ;此函数用C写成,统一处理   
  236.     add esp,8   
  237. ;清掉了error_code,int_vector   
  238.     jmp $   
  239. ;   hlt   
  240.   
  241. ;---------------------------------------------------------------------------SAVE   
  242. ;为下面的宏调用   
  243. Save:   
  244.     ;此时esp为当前进程PCB的寄存器栈   
  245.     ;的最高地址处   
  246.        
  247.     ;保存各寄存器到当前进程的PCB中   
  248.     pushad   
  249.     push    ds   
  250.     push    es   
  251.     push    gs   
  252.     push    fs   
  253.        
  254.     ;RING0下设置GDT下的段寄存器,注意bx被改变   
  255.     mov bx,Selector_Kernel_Flat_RW   
  256.     mov ds,bx   
  257.     mov es,bx   
  258.        
  259.     mov esi,esp                         ;esi指向当前进程的PCB的最低地址处   
  260.        
  261.     ;重入标志自增1后如果不等于0,则是发生了重入   
  262.     inc dword [d_Flag_Reenter]   
  263.     cmp dword [d_Flag_Reenter],0   
  264.     jne .1   
  265.        
  266.     mov esp,Top_Of_Kernel_Stack         ;堆栈顶指针也移动到内核空间中   
  267.        
  268.     push    Restart                     ;压入Restart,进程切换   
  269.     jmp [esi + Save_Ret_Addr_Offset]    ;回到调用Save的下一条语句   
  270.        
  271.     ;中断重入就压入Reenter,此时已进入内核栈   
  272. .1:   
  273.     push    Reenter                     ;压入Reenter,进程不切换   
  274.     jmp [esi + Save_Ret_Addr_Offset]    ;回到调用Save的下一条语句   
  275.   
  276. ;--------------------------------------------------------------HARD_INT_HANDLERS       
  277. ;初始化外中断处理程序的宏   
  278. %macro  hw  1   
  279.     ;保存寄存器值到当前进程的PCB等功能   
  280.     ;调用后下一条指令的地址入PCB的save_ret_addr字段   
  281.     call    Save   
  282.   
  283.     ;通知8259A此次中断已结束   
  284.     mov al,EOI   
  285.     mov dx,20h   
  286.     out dx,al   
  287.        
  288.     ;屏蔽当前向量号中断   
  289.     push    %1   
  290.     call    Enable_IRQ   
  291.     add esp,4   
  292.        
  293.     sti     ;发生中断时CPU自动关中断,这里人为打开   
  294.        
  295.     ;如果是时钟中断   
  296.     ;进程调度,中断重入不重入都调度,在函数内判断   
  297.     ;跳入相应的处理函数处理   
  298.     mov eax,IRQ_Handler_Table   
  299.     push    %1   
  300.     call    [eax + (%1 * 4)]        ;一个函数指针4字节   
  301.     add esp,4   
  302.        
  303.     cli     ;准备返回进程前关中断   
  304.        
  305.     ;恢复当前向量号中断   
  306.     push    %1   
  307.     call    Enable_IRQ   
  308.     add esp,4   
  309.        
  310.     ret     ;准备返回   
  311. %endmacro   
  312.   
  313. ;以下都是宏的扩展   
  314. hw_00:   
  315.     hw  0       ;时钟中断处理程序   
  316. hw_01:   
  317.     hw  1   
  318. hw_02:   
  319.     hw  2   
  320. hw_03:   
  321.     hw  3   
  322. hw_04:   
  323.     hw  4   
  324. hw_05:   
  325.     hw  5   
  326. hw_06:   
  327.     hw  6   
  328. hw_07:   
  329.     hw  7   
  330. hw_08:   
  331.     hw  8   
  332. hw_09:   
  333.     hw  9   
  334. hw_10:   
  335.     hw  10   
  336. hw_11:   
  337.     hw  11   
  338. hw_12:   
  339.     hw  12   
  340. hw_13:   
  341.     hw  13   
  342. hw_14:   
  343.     hw  14   
  344. hw_15:   
  345.     hw  15   
  346.        
  347. ;--------------------------------------------------------------------System_Call   
  348. System_Call:   
  349. ;由系统调用而进入到内核   
  350. ;保存各寄存器的值到当前进程的PCB中   
  351.     call    Save   
  352.        
  353.     ;压入2个参数,对于0,1号系统调用没有意义,而2号就有意义   
  354.     push    dword [p_Next_PCB]   
  355.     push    edx   
  356.     push    ecx   
  357.     push    edi   
  358.        
  359.     sti             ;发生中断时CPU自动关中断,这里人为打开   
  360.        
  361.     ;调用相应的处理函数   
  362.     call    [System_Call_Handler_Table + eax * 4]   
  363.     add esp,16      ;平衡堆栈   
  364.        
  365.     ;返回值写到PCB的EAX处,进程恢复时使用,对于1,2号系统调用没意义   
  366.     mov [esi + EAX_Offset],eax   
  367.        
  368.     cli     ;准备返回进程前关中断   
  369.        
  370.     ret     ;准备返回   
  371.        
  372. ;------------------------------------------------------------------STACK_SEGMENT   
  373. ;内核栈   
  374. [section .bss]   
  375. [bits 32]   
  376. LABEL_KERNEL_STACK_SPACE   
  377.     resb    2 * 1024   
  378. Top_Of_Kernel_Stack   
  379.        
  380. ;-----------------------------------------------------------Prepare_To_Real_Mode   
  381. [section .text]   
  382. [bits 32]   
  383. Prepare_To_Real_Mode:   
  384.     cli   
  385.   
  386.     ;设置实模式下的8259A   
  387.     mov al,00010111b   
  388.     out 20h,al   
  389.     nop   
  390.     nop   
  391.     nop   
  392.     nop   
  393.        
  394.     mov al,8h   
  395.     out 21h,al   
  396.     nop   
  397.     nop   
  398.     nop   
  399.     nop   
  400.        
  401.     mov al,1h   
  402.     out 21h,al   
  403.     nop   
  404.     nop   
  405.     nop   
  406.     nop   
  407.   
  408.     ;加载NORMAL描述符   
  409.     mov ax,Selector_Normal   
  410.     mov ds,ax   
  411.     mov es,ax   
  412.     mov gs,ax   
  413.     mov fs,ax   
  414.     mov ss,ax   
  415.        
  416.     ;跳到16位代码段准备回到实模式   
  417.     jmp Selector_Kernel_Flat_C_16:LABEL_CODE16   
  418.   
  419. ;-------------------------------------------------------------------DATA_SEGMENT   
  420. ;此段内容将被拷到0:8000h   
  421. [section .data]   
  422. [bits 32]   
  423. LABEL_DATA:   
  424.     ;sz_Clock_Int_Msg   db  '^',0   
  425.     b6_Old_IDTR_Value times 6   db  0       ;存放实模式下的IDTR值   
  426.     b_Old_IMR   db  0                       ;存放实模式下的IMR值   
  427. Data_Len    equ $ - LABEL_DATA   
  428.   
  429. ;------------------------------------------------------------------------Code_16   
  430. [section .text]   
  431. [bits 16]   
  432. LABEL_CODE16:   
  433.     ;关闭页表,切回实模式   
  434.     mov eax, cr0   
  435.     and eax, 7ffffffeh   
  436.     mov cr0, eax   
  437.        
  438.     ;跳转到1M空间内执行,即交给下面这段代码执行   
  439.     jmp 0:9000h   
  440.        
  441. ;下面的代码将被拷到0:9000h处   
  442. LABEL_ALREADY_REAL_MODE:   
  443.     ;初始化实模式下各段寄存器   
  444.     mov ax,cs   
  445.     mov ds,ax   
  446.     mov es,ax   
  447.     mov ss,ax   
  448.     mov sp,7000h   
  449.     mov gs,ax   
  450.     mov fs,ax   
  451.        
  452.     ;完成对8259A的设置   
  453.     mov al,[8006]   
  454.     out 21h,al   
  455.     lidt [8000]   
  456.        
  457.     ;关闭 A20 地址线   
  458.     in  al, 92h   
  459.     and al, 11111101b   
  460.     out 92h, al   
  461.        
  462.     ;设置一系列寄存器的初始值   
  463.     mov ax,0aa55h   
  464.     xor bx,bx   
  465.     xor cx,cx   
  466.     xor dx,dx   
  467.     xor bp,bp   
  468.     mov sp,0ffd6h   
  469.     mov si,3258h   
  470.     mov di,0ffach   
  471.        
  472.     ;重启   
  473.     jmp 0ffffh:0   
  474.        
  475. Code16_Len  equ $ - LABEL_ALREADY_REAL_MODE   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值