整理第五章的代码

    由上一篇文章看到,所写的内核的代码只存在于两个文件中,汇编写的一个,C写的一个,看起来乱得紧,改起来忒累人了。何况以后要写的代码就更多了,不可能老推在一起,得给它们分分家。

    首先按代码的性质分,一是一些常量啊,数据结构的定义啊,一些函数的声明啊等等,这些东东可以建一个文件夹来存放,命名为include;还有一些工具代码,如果显示个字符串之类的函数,可以建立一个lib的文件夹来存放它们;其它的就是一些跟内核相关的代码,如设置8259A,填充描述符的函数啊等等,就把它们把在一个kernel文件夹吧。至于前面的boot和loader等其它相关头文件全部放在boot文件夹里,这里不再赘述。

    首先从最简单的开始,从lib文件夹入手,首先把用汇编写的子程序拿出来放到一起,建立一个kliba.asm文件:

;=====================================================================
;               kliba.asm
;=====================================================================

extern Disp_Pos

[section .text]

global Out_Byte
global Disp_Color_Str

;Out_Byte=============================================================
;void Out_Byte(u16 port,u8 value);
Out_Byte:
 push ebp
 mov ebp,esp
 
 push eax
 push edx
 
 mov edx,[ebp + 8]
 mov eax,[ebp + 12]
 
 out dx,al
 
 nop
 nop
 
 pop edx
 pop eax
 
 pop ebp

 ret
;end of Out_Byte======================================================

;Disp_Color_Str=======================================================
;函数原型:void Disp_Color_Str(char * pszStr,u32 color);
;函数功能:在Disp_Str的基础上改变字符串的颜色
Disp_Color_Str:
 push ebp
 mov ebp,esp
 
 push eax
 push ebx
 push  esi
 push edi
 
 mov esi,[ebp + 8]           ;取得要显示的字符串的偏移
 mov edi,[Disp_Pos]
 xor eax,eax
 mov eax,[ebp + 12]
 shl eax,8
 and eax,0000ff00h           ;ah保存颜色
 
.begin:
 lodsb
 test al,al              ;如果字符为0就退出
 je .exit
 cmp al,0ah              ;如果是回车则跳到改变esi跳到下一行
 jne .disp
 push eax
 mov eax,edi
 mov bl,160
 div bl
 and ax,0ffh
 inc ax
 mov bl,160
 mul bl
 mov edi,eax
 pop eax
 jmp .begin
.disp:
 mov [gs:edi],ax
 add edi,2
 jmp .begin
.exit:
 mov [Disp_Pos],edi          ;全局变量赋回值     
 
 pop edi
 pop esi
 pop ebx
 pop eax
 
 pop ebp

 ret
;end of Disp_Color_Str================================================

    除此之外,还有一些用C写的函数,放到klib.c文件中,其中包含了一些头文件,待会儿再解释:

Code:
  1. /*====================================================================  
  2.                                klib.c  
  3. ====================================================================*/  
  4.   
  5. #include "type.h"   
  6. #include "proto.h"
  7.   
  8. /*======================================================================*  
  9.                                itoa  
  10.  *======================================================================*/  
  11. /* 数字前面的 0 不被显示出来, 比如 0000B800 被显示成 B800 */  
  12. char * itoa(char * str, int num)   
  13. {   
  14.     char *p = str;   
  15.     char    ch;   
  16.     int i;   
  17.     int flag = 0;   
  18.   
  19.     *p++ = '0';   
  20.     *p++ = 'x';   
  21.   
  22.     if(num == 0){   
  23.         *p++ = '0';   
  24.     }   
  25.     else{      
  26.         for(i=28;i>=0;i-=4){   
  27.             ch = (num >> i) & 0xF;   
  28.             if(flag || (ch > 0)){   
  29.                 flag = 1;   
  30.                 ch += '0';   
  31.                 if(ch > '9'){   
  32.                     ch += 7;   
  33.                 }   
  34.                 *p++ = ch;   
  35.             }   
  36.         }   
  37.     }   
  38.   
  39.     *p = 0;   
  40.   
  41.     return str;   
  42. }   
  43.   
  44. /*======================================================================*  
  45.                                Disp_Int  
  46.  *======================================================================*/  
  47. void Disp_Int(u32 num)   
  48. {   
  49.     char output[16];   
  50.     itoa(output, num);   
  51.     Disp_Color_Str(output,0xc);   
  52. }  

    搞定了lib,再来到include文件夹,主要是定义一些头文件。我们定义了一些类型,如u32,u16等,我们建立一个type.h文件:

Code:
  1. /*====================================================================  
  2.                               type.h  
  3. ====================================================================*/  
  4.   
  5. #ifndef _TYPE_H_   
  6. #define _TYPE_H_   
  7.   
  8.     typedef unsigned char  u8;       
  9.     typedef unsigned short u16;      
  10.     typedef unsigned int   u32;       
  11.        
  12.     typedef void (*Int_Handler)();   
  13.   
  14. #endif  

    接下来是一些函数的声明,放到proto.h文件中:

Code:
  1. /*====================================================================  
  2.                                proto.h  
  3. ====================================================================*/  
  4.   
  5. #ifndef _PROTO_H_   
  6. #define _PROTO_H_   
  7.   
  8.     void Disp_Color_Str(char *p_Str,u32 color);   
  9.     void Disp_Int(u32 num);   
  10.     void Out_Byte(u16 port,u8 value);   
  11.        
  12.     void Fill_Desc(u8 desc_no,u32 base,u32 limit,u16 attr);   
  13.     void Fill_Gate(u8 idt_no,Int_Handler handler,u8 type,u8 privilege);   
  14.     void Init_GDT();   
  15.     void Init_IDT();   
  16.     void Init_8259A();   
  17.     void Exception_Handler(u32 vec_no,u32 err_code,u32 eip,u32 cs,int eflags);   
  18.     void IRQ_Handler(u32 irq_no);   
  19.        
  20.     /* 中断处理函数 */  
  21.     void    Divide_Error();   
  22.     void    Single_Step_Exception();   
  23.     void    NMI();   
  24.     void    Breakpoint_Exception();   
  25.     void    Overflow();   
  26.     void    Bounds_Check();   
  27.     void    Inval_Opcode();   
  28.     void    Copr_Not_Available();   
  29.     void    Double_Fault();   
  30.     void    Copr_Seg_Overrun();   
  31.     void    Inval_TSS();   
  32.     void    Segment_Not_Present();   
  33.     void    Stack_Exception();   
  34.     void    General_Protection();   
  35.     void    Page_Fault();   
  36.     void    Copr_Error();   
  37.        
  38.     void  HW_Int_00();   
  39.     void  HW_Int_01();   
  40.     void  HW_Int_02();   
  41.     void  HW_Int_03();   
  42.     void  HW_Int_04();   
  43.     void  HW_Int_05();   
  44.     void  HW_Int_06();   
  45.     void  HW_Int_07();   
  46.     void  HW_Int_08();   
  47.     void  HW_Int_09();   
  48.     void  HW_Int_10();   
  49.     void  HW_Int_11();   
  50.     void  HW_Int_12();   
  51.     void  HW_Int_13();   
  52.     void  HW_Int_14();   
  53.     void  HW_Int_15();   
  54.   
  55. #endif   

    接下来是定义一些与保护模式相关的常量与数据结构声明,放在protect.h中:

Code:
  1. /*====================================================================  
  2.                                protect.h  
  3. ====================================================================*/  
  4.   
  5. #ifndef _PROTECT_H_   
  6. #define _PROTECT_H_   
  7.   
  8.     /* 描述符类型值说明 */      
  9.     #define DA_32               0x4000              /* 32 位段              */         
  10.     #define DA_LIMIT_4K         0x8000              /* 段界限粒度为 4K 字节   */       
  11.     #define DA_DPL0             0x00                /* DPL = 0              */       
  12.     #define DA_DPL1             0x20                /* DPL = 1              */       
  13.     #define DA_DPL2             0x40                /* DPL = 2              */       
  14.     #define DA_DPL3             0x60                /* DPL = 3              */       
  15.                
  16.     /* 存储段描述符类型值说明 */      
  17.     #define DA_DR               0x90                /* 存在的只读数据段类型值          */       
  18.     #define DA_DRW              0x92                /* 存在的可读写数据段属性值        */       
  19.     #define DA_DRWA             0x93                /* 存在的已访问可读写数据段类型值   */       
  20.     #define DA_C                0x98                /* 存在的只执行代码段属性值        */       
  21.     #define DA_CR               0x9A                /* 存在的可执行可读代码段属性值     */       
  22.     #define DA_CCO              0x9C                /* 存在的只执行一致代码段属性值     */       
  23.     #define DA_CCOR             0x9E                /* 存在的可执行可读一致代码段属性值 */       
  24.                
  25.     /* 系统段描述符类型值说明 */      
  26.     #define DA_LDT              0x82                /* 局部描述符表段类型值           */       
  27.     #define DA_TaskGate         0x85                /* 任务门类型值                  */        
  28.     #define DA_386TSS           0x89                /* 可用 386 任务状态段类型值      */       
  29.     #define DA_386CGate         0x8C                /* 386 调用门类型值              */       
  30.     #define DA_386IGate         0x8E                /* 386 中断门类型值              */       
  31.     #define DA_386TGate         0x8F                /* 386 陷阱门类型值              */       
  32.        
  33.     /* 权限 */  
  34.     #define PRIVILEGE_KRNL  0   
  35.     #define PRIVILEGE_TASK  1   
  36.     #define PRIVILEGE_USER  3   
  37.        
  38.     /* 中断向量 */  
  39.     #define INT_VECTOR_DIVIDE               0x0   
  40.     #define INT_VECTOR_DEBUG                0x1   
  41.     #define INT_VECTOR_NMI                  0x2   
  42.     #define INT_VECTOR_BREAKPOINT           0x3   
  43.     #define INT_VECTOR_OVERFLOW             0x4        
  44.     #define INT_VECTOR_BOUNDS               0x5   
  45.     #define INT_VECTOR_INVAL_OP             0x6   
  46.     #define INT_VECTOR_COPROC_NOT           0x7   
  47.     #define INT_VECTOR_DOUBLE_FAULT         0x8   
  48.     #define INT_VECTOR_COPROC_SEG           0x9   
  49.     #define INT_VECTOR_INVAL_TSS            0xA   
  50.     #define INT_VECTOR_SEG_NOT              0xB   
  51.     #define INT_VECTOR_STACK_FAULT          0xC   
  52.     #define INT_VECTOR_PROTECTION           0xD   
  53.     #define INT_VECTOR_PAGE_FAULT           0xE   
  54.     #define INT_VECTOR_COPROC_ERR           0x10   
  55.        
  56.     typedef struct s_descriptor       
  57.     {       
  58.         u16 limit_low;                 /* limit(0..15) */      
  59.         u16 base_low;                  /* base(0..15) */      
  60.         u8  base_mid;                  /* base(16..23) */      
  61.         u8  attr1;                     /* P(1) DPL(2) S(1) TYPE(4)*/      
  62.         u8  limit_high_attr2;          /* G(1) D/B(1) O(1) AVL(1) limit(16..19) */      
  63.     u8  base_high;                     /* base(24..31) */      
  64.     }Descriptor;       
  65.   
  66.     typedef struct s_gate   
  67.     {   
  68.         u16 offset_low;                /* offset(0..15) */  
  69.         u16 selector;                  /* selector */  
  70.         u8  dcount;    
  71.         u8  attr;                      /* P(1) DPL(2) S(1) TYPE(4) */  
  72.         u16 offset_high;                                                                      
  73.     }Gate;   
  74.   
  75. #endif  

     我们还想把全局变量分开来放,所以还得建立一个global.h文件来存放全局变量的声明:

Code:
  1. /*====================================================================  
  2.                             global.h  
  3. ====================================================================*/  
  4.   
  5. #ifndef _GLOBAL_H_   
  6. #define _GLOBAL_H_   
  7.        
  8.     extern Descriptor GDT[128];       
  9.     extern u8 GDT_Ptr[6];       
  10.     extern Gate IDT[256];   
  11.     extern u8 IDT_Ptr[6];   
  12.     extern u32 Disp_Pos;   
  13.   
  14. #endif  

    好了,include文件夹的内容也完成了,最后来到kernel文件夹。

    先把初始化8259A的代码和外中断处理代码抽取出来,形成i8259.c:

Code:
  1. /*====================================================================  
  2.                               i8259.c  
  3. ====================================================================*/  
  4.   
  5. #include "type.h"   
  6. #include "proto.h"   
  7.   
  8. void Init_8259A()   
  9. {   
  10.     Out_Byte(0x20,0x11);   
  11.     Out_Byte(0xa0,0x11);   
  12.        
  13.     Out_Byte(0x21,0x20);   
  14.     Out_Byte(0xa1,0x28);   
  15.        
  16.     Out_Byte(0x21,0x4);   
  17.     Out_Byte(0xa1,0x2);   
  18.        
  19.     Out_Byte(0x21,0x1);   
  20.     Out_Byte(0xa1,0x1);   
  21.        
  22.     Out_Byte(0x21,0xfd);   
  23.     Out_Byte(0xa1,0xff);   
  24. }   
  25.   
  26. void IRQ_Handler(u32 irq_no)   
  27. {   
  28.     Disp_Color_Str("IRQ_NO:",0xd);   
  29.     Disp_Int(irq_no);   
  30.     Disp_Color_Str("/n",0xd);   
  31. }  

    接着把与保护模式的相关代码聚集起来形成protect.c:

Code:
  1. /*====================================================================  
  2.                                protect.c  
  3. ====================================================================*/  
  4.   
  5. #include "type.h"   
  6. #include "proto.h"   
  7. #include "protect.h"   
  8. #include "global.h"   
  9.   
  10. void Fill_Desc(u8 desc_no,u32 base,u32 limit,u16 attr)       
  11. {       
  12.     Descriptor *p_Desc = (Descriptor *)&GDT[desc_no];       
  13.     p_Desc->limit_low = limit & 0xffff;       
  14.     p_Desc->base_low = base & 0xffff;       
  15.     p_Desc->base_mid = (base >> 16) & 0xff;       
  16.     p_Desc->attr1 = attr & 0xff;       
  17.     p_Desc->limit_high_attr2 = ((limit >> 16) & 0xf) | (attr >> 8);       
  18.     p_Desc->base_high = (base >> 24) & 0xff;       
  19. }       
  20.       
  21. void Init_GDT()       
  22. {       
  23.     Fill_Desc(0,0,0,0);       
  24.     Fill_Desc(1,0,0xfffff,DA_DRW | DA_32 | DA_LIMIT_4K);       
  25.     Fill_Desc(2,0,0xfffff,DA_C | DA_32 | DA_LIMIT_4K);       
  26.     Fill_Desc(3,0xb8000,0xffff,DA_DRW);       
  27. }       
  28.   
  29. void Fill_Gate(u8 idt_no,Int_Handler handler,u8 type,u8 privilege)   
  30. {   
  31.     Gate *p_Gate = (Gate*)&IDT[idt_no];   
  32.     u32 base = (u32)handler;   
  33.     p_Gate->offset_low = base & 0xffff;   
  34.     p_Gate->selector = 16;   
  35.     p_Gate->dcount = 0;   
  36.     p_Gate->attr = type | (privilege << 5);   
  37.     p_Gate->offset_high = (base >> 16) & 0xffff;   
  38. }   
  39.   
  40. void Init_IDT()   
  41. {   
  42.     Fill_Gate(INT_VECTOR_DIVIDE,Divide_Error,DA_386IGate,PRIVILEGE_KRNL);   
  43.     Fill_Gate(INT_VECTOR_DEBUG,Single_Step_Exception,DA_386IGate,PRIVILEGE_KRNL);   
  44.     Fill_Gate(INT_VECTOR_NMI,NMI,DA_386IGate,PRIVILEGE_KRNL);   
  45.     Fill_Gate(INT_VECTOR_BREAKPOINT,Breakpoint_Exception,DA_386IGate,PRIVILEGE_KRNL);   
  46.     Fill_Gate(INT_VECTOR_OVERFLOW,Overflow,DA_386IGate,PRIVILEGE_KRNL);   
  47.     Fill_Gate(INT_VECTOR_BOUNDS,Bounds_Check,DA_386IGate,PRIVILEGE_KRNL);   
  48.     Fill_Gate(INT_VECTOR_INVAL_OP,Inval_Opcode,DA_386IGate,PRIVILEGE_KRNL);   
  49.     Fill_Gate(INT_VECTOR_COPROC_NOT,Copr_Not_Available,DA_386IGate,PRIVILEGE_KRNL);   
  50.     Fill_Gate(INT_VECTOR_DOUBLE_FAULT,Double_Fault,DA_386IGate,PRIVILEGE_KRNL);   
  51.     Fill_Gate(INT_VECTOR_COPROC_SEG,Copr_Seg_Overrun,DA_386IGate,PRIVILEGE_KRNL);   
  52.     Fill_Gate(INT_VECTOR_INVAL_TSS,Inval_TSS,DA_386IGate,PRIVILEGE_KRNL);   
  53.     Fill_Gate(INT_VECTOR_SEG_NOT,Segment_Not_Present,DA_386IGate,PRIVILEGE_KRNL);   
  54.     Fill_Gate(INT_VECTOR_STACK_FAULT,Stack_Exception,DA_386IGate,PRIVILEGE_KRNL);   
  55.     Fill_Gate(INT_VECTOR_PROTECTION,General_Protection,DA_386IGate,PRIVILEGE_KRNL);   
  56.     Fill_Gate(INT_VECTOR_PAGE_FAULT,Page_Fault,DA_386IGate,PRIVILEGE_KRNL);   
  57.     Fill_Gate(INT_VECTOR_COPROC_ERR,Copr_Error,DA_386IGate,PRIVILEGE_KRNL);   
  58.        
  59.     Fill_Gate(0x20,HW_Int_00,DA_386IGate,PRIVILEGE_KRNL);   
  60.     Fill_Gate(0x21,HW_Int_01,DA_386IGate,PRIVILEGE_KRNL);   
  61.     Fill_Gate(0x22,HW_Int_02,DA_386IGate,PRIVILEGE_KRNL);   
  62.     Fill_Gate(0x23,HW_Int_03,DA_386IGate,PRIVILEGE_KRNL);   
  63.     Fill_Gate(0x24,HW_Int_04,DA_386IGate,PRIVILEGE_KRNL);   
  64.     Fill_Gate(0x25,HW_Int_05,DA_386IGate,PRIVILEGE_KRNL);   
  65.     Fill_Gate(0x26,HW_Int_06,DA_386IGate,PRIVILEGE_KRNL);   
  66.     Fill_Gate(0x27,HW_Int_07,DA_386IGate,PRIVILEGE_KRNL);   
  67.     Fill_Gate(0x28,HW_Int_08,DA_386IGate,PRIVILEGE_KRNL);   
  68.     Fill_Gate(0x29,HW_Int_09,DA_386IGate,PRIVILEGE_KRNL);   
  69.     Fill_Gate(0x2a,HW_Int_10,DA_386IGate,PRIVILEGE_KRNL);   
  70.     Fill_Gate(0x2b,HW_Int_11,DA_386IGate,PRIVILEGE_KRNL);   
  71.     Fill_Gate(0x2c,HW_Int_12,DA_386IGate,PRIVILEGE_KRNL);   
  72.     Fill_Gate(0x2d,HW_Int_13,DA_386IGate,PRIVILEGE_KRNL);   
  73.     Fill_Gate(0x2e,HW_Int_14,DA_386IGate,PRIVILEGE_KRNL);   
  74.     Fill_Gate(0x2f,HW_Int_15,DA_386IGate,PRIVILEGE_KRNL);   
  75. }   
  76.   
  77. void Exception_Handler(u32 vec_no,u32 err_code,u32 eip,u32 cs,int eflags)   
  78. {   
  79.     int i;   
  80.        
  81.     Disp_Pos = 0;   
  82.     for(i = 0 ; i < 80 * 5 ; i++)   
  83.     {   
  84.         Disp_Color_Str(" ",0xc);   
  85.     }   
  86.     Disp_Pos = 0;   
  87.        
  88.     Disp_Color_Str("VEC_NO:",0xc);   
  89.     Disp_Int(vec_no);   
  90.     Disp_Color_Str("/n",0xc);   
  91.        
  92.     Disp_Color_Str("ERROR_CODE:",0xc);   
  93.     Disp_Int(err_code);   
  94.     Disp_Color_Str("/n",0xc);   
  95.        
  96.     Disp_Color_Str("CS:",0xc);   
  97.     Disp_Int(cs);   
  98.     Disp_Color_Str("/n",0xc);   
  99.        
  100.     Disp_Color_Str("EIP:",0xc);   
  101.     Disp_Int(eip);   
  102.     Disp_Color_Str("/n",0xc);   
  103.        
  104.     Disp_Color_Str("EFLAGS:",0xc);   
  105.     Disp_Int(eflags);   
  106.     Disp_Color_Str("/n",0xc);   
  107. }  

    接下来是把全部变量的定义放在global.c中:

Code:
  1. /*====================================================================  
  2.                              global.c  
  3. ====================================================================*/  
  4.   
  5. #include "type.h"   
  6. #include "protect.h"   
  7.   
  8. Descriptor GDT[128];       
  9. u8 GDT_Ptr[6];       
  10. Gate IDT[256];   
  11. u8 IDT_Ptr[6];   
  12. u32 Disp_Pos;  

    接着是大管家start.c文件,它负责调用其它的函数:

Code:
  1. /*====================================================================  
  2.                               start.c  
  3. ====================================================================*/  
  4.   
  5. #include "type.h"   
  6. #include "proto.h"   
  7. #include "protect.h"   
  8. #include "global.h"   
  9.   
  10. void C_Start()       
  11. {       
  12.     Init_8259A();   
  13.     Init_GDT();       
  14.     Init_IDT();   
  15.     *(u16*)(&GDT_Ptr[0]) = 4 * 8 - 1;       
  16.     *(u32*)(&GDT_Ptr[2]) = (u32)&GDT;    
  17.     *(u16*)(&IDT_Ptr[0]) = sizeof(Gate) * 256 - 1;   
  18.         *(u32*)(&IDT_Ptr[2]) = (u32)&IDT;      
  19. }     

    最后是kernel.asm文件:

extern GDT_Ptr
extern IDT_Ptr
extern Disp_Pos
extern C_Start
extern Exception_Handler
extern IRQ_Handler

Selector_Loader_Flat_RW  equ  8

Selector_Kernel_Flat_RW   equ   8
Selector_Kernel_Flat_C  equ  16
Selector_Kernel_Video   equ  24

[section .bss]

Stack_Space resb 2 * 1024
Top_Of_Stack:

[section .text]

global Divide_Error
global Single_Step_Exception
global NMI
global Breakpoint_Exception
global Overflow
global Bounds_Check
global Inval_Opcode
global Copr_Not_Available
global Double_Fault
global Copr_Seg_Overrun
global Inval_TSS
global Segment_Not_Present
global Stack_Exception
global General_Protection
global Page_Fault
global Copr_Error

global HW_Int_00
global HW_Int_01
global HW_Int_02
global HW_Int_03
global HW_Int_04
global HW_Int_05
global HW_Int_06
global HW_Int_07
global HW_Int_08
global HW_Int_09
global HW_Int_10
global HW_Int_11
global HW_Int_12
global HW_Int_13
global HW_Int_14
global HW_Int_15

global Out_Byte
global Disp_Color_Str

global _start

_start:
 mov ax,Selector_Loader_Flat_RW
 mov ds,ax
 mov es,ax
 
 call C_Start
 
 lgdt [GDT_Ptr]
 lidt [IDT_Ptr]
 
 mov ax,Selector_Kernel_Flat_RW
 mov ds,ax
 mov es,ax
 mov ss,ax
 mov esp,Top_Of_Stack 
 mov ax,Selector_Kernel_Video
 mov gs,ax
 
 jmp Selector_Kernel_Flat_C:_test
 
_test:
 ;jmp 100:0
 sti
 hlt

Divide_Error:
 push 0ffffffffh
 push 0
 jmp Exception
Single_Step_Exception:
 push 0ffffffffh
 push 1
 jmp Exception
NMI:
 push 0ffffffffh
 push 2
 jmp Exception
Breakpoint_Exception:
 push 0ffffffffh
 push 3
 jmp Exception
Overflow:
 push 0ffffffffh
 push 4
 jmp Exception
Bounds_Check:
 push 0ffffffffh
 push 5
 jmp Exception
Inval_Opcode:
 push 0ffffffffh
 push 6
 jmp Exception
Copr_Not_Available:
 push 0ffffffffh
 push 7
 jmp Exception
Double_Fault:
 push 8
 jmp Exception
Copr_Seg_Overrun:
 push 0ffffffffh
 push 9
 jmp Exception
Inval_TSS:
 push 10
 jmp Exception
Segment_Not_Present:
 push 11
 jmp Exception
Stack_Exception:
 push 12
 jmp Exception
General_Protection:
 push 13
 jmp Exception
Page_Fault:
 push 14
 jmp Exception
Copr_Error:
 push 0ffffffffh
 push 16
 jmp Exception
Exception:
 call Exception_Handler
 add esp,8
 hlt
 
HW_Int_00:
 push 0;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_01:
 push 1;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_02:
 push 2;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_03:
 push 3;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_04:
 push 4;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_05:
 push 5;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_06:
 push 6;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_07:
 push 7;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_08:
 push 8;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_09:
 push 9;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_10:
 push 10;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_11:
 push 11;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_12:
 push 12;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_13:
 push 13;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_14:
 push 14;
 call IRQ_Handler
 add  esp,4
 hlt
HW_Int_15:
 push 15;
 call IRQ_Handler
 add  esp,4
 hlt

  真累啊,终于搞定了,让我们来编译链接一下吧,假定我们在各子目录的父目录:

   nasm -f elf -o ./kernel/kernel.o ./kernel/kernel.asm

   nasm -f elf -o ./lib/kliba.o ./lib/kliba.asm

   gcc -c -I ./include -o ./kernel/i8259.o ./kernel/i8259.c

   gcc -c -I ./include -o ./kernel/protect.o ./kernel/protect.c

   gcc -c -I ./include -o ./kernel/global.o ./kernel/global.c

   gcc -c -I ./include -o ./kernel/start.o ./kernel/start.c

   gcc -c -I ./include -o ./lib/klib.o ./kernel/i8259.c

   ld -s -Ttext 0x30400 -o  kernel.bin ./kernel/kernel.o ./kernel/start.o ./kernel/i8259.o /

./kernel/protect.o ./kernel/global.o ./lib/kliba.o ./lib/klib.o

  我们可以看到,为了编译链接一个kernel.bin,就要写那么多条命令,要是在调试过程中哪里出错了要重新编译链接,每一次都要输入那么多条命令简直就是灾难,况且我们的胎盘操作系统的路还没走多少,以后随着代码量的增大,要建立更多的文件和文件夹,你自己可以想象一下这个工作量了。

  不过,还有MAKEFILE这个强大的工具可以供我们使用,我们只需要写个MAKEFILE,就可以轻松的让计算机帮我们完成这个龌龊繁琐的任务,明天再来研究,上床手机MOP咯。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
数据结构与算法是计算机科学的基础和核心领域之一,第ba章介绍了数据结构的相关内容。 本章主要包括以下几个方面的内容: 1. 线性结构:线性结构是指数据元素之间存在一对一的关系,包括线性表、栈和队列。线性表是最基本的数据结构之一,它分为顺序表和链表两种形式。顺序表使用数组实现,插入和删除操作相对低效。链表使用指针实现,插入和删除操作较为灵活。 2. 树结构:树结构是一种层次结构,由节点和边组成。常见的树结构有二叉树、二叉搜索树和平衡二叉树等。二叉树中每个节点最多有两个子节点,二叉搜索树中左子节点的值小于根节点,右子节点的值大于根节点,查找效率较高。平衡二叉树是一种保持左右子树高度差不大于1的二叉搜索树。 3. 图结构:图结构是由节点和边组成的非线性结构。图分为有向图和无向图。图的表示方法有邻接矩阵和邻接表两种。深度优先搜索和广度优先搜索是图的常用遍历方法,可用于寻找路径、连通分量等问题。 4. 排序算法:排序算法是对一组无序数据进行按照某个规则进行有序排列的算法。第ba章介绍了常见的排序算法,包括冒泡排序、插入排序、选择排序、归并排序、快速排序等。每种排序算法的时间复杂度和空间复杂度不同,选择合适的排序算法可以提高性能。 5. 查找算法:查找算法是在一组数据中搜索某个特定元素的算法。第ba章介绍了顺序查找、二分查找和哈希查找等常见的查找算法。二分查找是在有序数组中应用最广泛的查找算法,通过不断缩小查找范围来快速定位目标值。 通过学习这些内容,我们可以了解不同数据结构的特点和应用场景,以及常见的排序和查找算法。掌握好这些知识,对于解决实际问题和提高程序效率都有很大帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值