整理文件夹

目前我们所有的文件都在一个文件夹下,目录结构如下

整理文件夹_第1张图片

以后代码越来越多,管理起来很不方便,下面我们就仿照linux的目录结构来整理一下:新建一个boot文件夹,将bootsect.S、head.S、setup.S此文件夹下;新建include文件夹,在此文件夹下新建asm和linux文件夹,asm文件夹下添加io.h和system.h,linux文件夹下添加head.h;新建init文件夹并将main.c放到此文件夹下;新建kernel文件夹并将asm.S和kliba.S放到此文件下,另外再新建一个Trap.c文件。

整理后目录结构如下:

整理文件夹_第2张图片

io.h中放和io相关的代码,将mian.c中相关代码放到io.h中

#define outb(value,port) \
__asm__ ("outb %%al,%%dx"::"a" (value),"d" (port))

 

system.h文件

#define sti() __asm__ ("sti"::)
#if 1
#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ ("movw %%dx,%%ax\n\t" \
	"movw %0,%%dx\n\t" \
	"movl %%eax,%1\n\t" \
	"movl %%edx,%2" \
	: \
	: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
	"o" (*((char *) (gate_addr))), \
	"o" (*(4+(char *) (gate_addr))), \
	"d" ((char *) (addr)),"a" (0x00080000))
#else

typedef	unsigned int		u32;
typedef	unsigned short	u16;
typedef	unsigned char		u8;	
	
typedef struct s_gate
{
	u16	offset_low;
	u16	selector;	
	u8	dcount;		 
	u8	attr;		
	u16	offset_high;
}GATE;	
void _set_gate(GATE *gate_addr,u8 type,u8 dpl,void (*addr)())	
{
	gate_addr->offset_low	= ((u32)addr) & 0xFFFF;
	gate_addr->selector	= 0x08;
	gate_addr->dcount		= 0;
	gate_addr->attr		= type | (dpl << 5);
	gate_addr->offset_high	= ((u32)addr >> 16) & 0xFFFF;
		
}
#endif

#define set_intr_gate(n,addr) \
	_set_gate(&idt[n],14,0,addr)
#define set_trap_gate(n,addr) \
	_set_gate(&idt[n],15,0,addr)


head.h

#ifndef _HEAD_H
#define _HEAD_H

typedef struct desc_struct {
	unsigned long a,b;
} desc_table[256];

extern unsigned long pg_dir[1024];
extern desc_table idt,gdt;

#endif


Trap.c

#include 
#include 
extern void divide_error(void);
int i =0;	
void do_divide_error(void)
{
	i++;
	disp_int(i);
  outb(0x20,0x20);
}


整理后的main.c

#include 
#include 
#include 
extern void divide_error(void);

void disp_str(char *info);


void main(void)		
{
	disp_str("How old are you?\n");
	set_intr_gate(32,÷_error);
	sti();
	disp_int(0x12345678);
	while(1);
}


为了和linux内核统一便于以后分析,我们在在head.S中添加idt和gdt标号,head.S

#define Descriptor(base,lim,attr)\
.word lim&0xffff;\
.word base&0xffff;\
.byte (base>>16)&0xff;\
.word ((lim>>8)&0xf00)|(attr&0x0f0ff);\
.byte ((base>>24)&0xff)    

#define Gate(Selector,Offset,PCount,Attr)\  
.2byte (Offset&0xffff);\  
.2byte (Selector);\  
.2byte (PCount&0x1f)|((Attr<<8)&0xff00);\  
.2byte ((Offset>>16)&0xffff) 
  
   
DA_32=0x4000          //32位模式
DA_LIMIT_4K=0x8000          //颗粒度为4096
DA_DRW=0x92            //数据段可读可写
DA_CR=0x9A            //可读可执行
DA_C   = 0x98 
SETUPSEG = 0x9020
SETUPAddr = SETUPSEG<<4
DA_386CGate = 0x8c 
DA_386IGate = 0x8E 
DA_PL0 = 0x00

.text  
.globl start,idt,gdt/*程序从start处开始运行*/  
.code32 
_pg_dir://页目录将会存放在这里 
start:
		movl     $0x20,%eax     
    mov     %ax,%ds //因为ds是数据段寄存器,所以要加载一个数据段,否则会发生异常(可以试试0x08描述符)
    mov     %ax,%es      
    mov     %ax,%ss    
    mov  $0xffff,%esp 
/*加载gdtr即将全局描述符表gdt的首地址和gdt的界限赋给gdtr寄存器*/         
    lgdt GdtPtr 
    lidt IdtPtr
    movl     $0x20,%eax     
    mov     %ax,%ds   
    mov     %ax,%es      
    mov     %ax,%ss    
    mov  $0xffff,%esp

 
    ljmp $0x8,$LABEL_SEG_CODE32
    
.align  4    
LABEL_SEG_CODE32:  
.code32  

    movw $0x10,%ax  
    movw %ax,%gs  
    movl $((80*12+79)*2),%edi/*第12行,79列*/  
    movb $0x0c,%ah/*高四位表示黑底,低四位表示红字*/  
    movb $'S',%al/*显示的字符*/  
    movw %ax,%gs:(%edi)  

    int $0x80
    //sti
   
    jmp after_page_tables
              
loop1:/*无限循环*/  
    jmp loop1 
   
.align  4
INT_TEST:  
.code32   

    movl $((80*13+79)*2),%edi/*第11行,79列*/  
    movb $0x0c,%ah/*高四位表示黑底,低四位表示红字*/  
    movb $'I',%al/*显示的字符*/  
    movw %ax,%gs:(%edi) 
    iret             
loop2:/*无限循环*/  
    jmp loop2    
 
 
/*
*每个页表长4kb字节,而每个页表项需要4个字节,因此一个页表可以存放1024个表项
*/       
.org 0x1000
pg0:

.org 0x2000
pg1:

.org 0x3000
pg2:

.org 0x4000
pg3:

.org 0x5000//定义下面的内存块从0x5000开始

//软盘缓冲区
_tmp_floppy_area:
	.fill 1024,1,0 //预留1024项,每项1字节,填充数值为0
	
after_page_tables:
	pushl $0
	pushl $0
	pushl $0
	pushl $L6
	pushl $main
	jmp setup_paging
L6:
	jmp L6
	
int_msg:
	.asciz "Unknown interrupt\n\r"
.align  4
ignore_int:  
.code32   

    movl $((80*13+79)*2),%edi/*第11行,79列*/  
    movb $0x0c,%ah/*高四位表示黑底,低四位表示红字*/  
    movb $'I',%al/*显示的字符*/  
    movw %ax,%gs:(%edi) 
    iret             
loop21:/*无限循环*/  
    jmp loop21 
.align  4
ClockHandler:  
    movl $((80*14+79)*2),%edi
    movw %gs:(%edi),%ax
    add  $1,%ax
    movw %ax,%gs:(%edi)
    movb $0x20,%al
    out %al,$0x20
    
    iret
                  
loop3:/*无限循环*/  
    jmp loop3    
    ret 
.align 4 //按4字节方式对齐内存地址边界	    
setup_paging: //先对5页内存清零(1页目录+4页页表)
	movl $1024*5,%ecx
	xorl %eax,%eax
	xorl %edi,%edi
	//重复执行rep下面的语句,每次ecx减一,直到ecx为0 
	//页目录从0x00地址开始
	cld;rep;stosl //eax内容存到es:edi所指内存位置,且edi增4
//STOSL指令相当于将EAX中的值保存到ES:EDI指向的地址中,若设置了EFLAGS中的方向位置位(即在STOSL指令前使用STD指令)则EDI自减4,否则(使用CLD指令)EDI自增4。
	
	//设置页目录
	movl $pg0+7,_pg_dir//7表示该页存在、用户可读写
	movl $pg1+7,_pg_dir+4
	movl $pg2+7,_pg_dir+8
	movl $pg3+7,_pg_dir+12
	
	//设置页表,共有4个页表,每个页表1024
	movl $pg3+4092,%edi
	movl $0xfff007,%eax//16Mb - 4096 + 7 = 0xfff007
	
	//cld,清方向标志,即(DF)=0,地址从低到高
  //std,置方向标志1,DF=1,地址从高到低
	std//std(set direction)置方向标志
1:
	stosl
	subl $0x1000,%eax
	jge 1b
	
	xorl %eax,%eax
	movl %eax,%cr3
	
	movl %cr0,%eax
	orl	$0x80000000,%eax
	movl %eax,%cr0
	//jmp Page_test
	ret
	/**/

.align  4 
.word 0
IdtPtr:    
    .word (END_IDT-LABEL_IDT)-1 # so does gdt     
    .long LABEL_IDT     # This will be rewrite by code. 
    
.align  4 
.word 0
GdtPtr:  
    .word (GDT_END-GDT_START)-1 # so does gdt   
    .long GDT_START     # This will be rewrite by code.    
.align  8 
idt:
LABEL_IDT:   
.rep 32
				Gate(0x08,(ignore_int - start),0,(DA_386IGate+DA_PL0))	
.endr

	Gate(0x08,(ClockHandler - start),0,(DA_386IGate+DA_PL0))

.rep 222
				Gate(0x08,(ignore_int - start),0,(DA_386IGate+DA_PL0))	
.endr

END_IDT:
 

gdt:
GDT_START:    
Descriptor_DUMMY:Descriptor(0x0,0x0,0x0)  
Descriptor_CODE32 :Descriptor(0x0,0xffffffff,DA_C+DA_32)  
Descriptor_VIDEO:Descriptor(0xb8000,0x0ffff,DA_DRW) 
Descriptor_SYSTM :Descriptor(0x00000,0xffffffff,DA_C+DA_32) 
Descriptor_SYSTM2 :Descriptor(0x00000,0xffffffff,DA_DRW) 
.fill 251,8,0			/* space for LDT's and TSS's etc */
GDT_END:  
  


最后我们修改makefile

# Makefile for the simple example kernel.
AS    =as
LD    =ld
LDFLAGS   = --oformat binary -N -e start -Ttext 0x0

Image:bootsect setup system
	cat bootsect setup system >Image
	
bootsect:boot/bootsect.s
	$(AS) -o bootsect.o -a boot/bootsect.s
	$(LD) $(LDFLAGS) -o bootsect bootsect.o
setup:boot/setup.s
	$(AS) -o setup.o -a boot/setup.s
	$(LD) $(LDFLAGS) -o setup setup.o
head.o:boot/head.s
	$(AS) -o head.o -a boot/head.s
asm.o:kernel/asm.s
	$(AS) -o asm.o -a kernel/asm.s
kliba.o:kernel/kliba.s
	$(AS) -o kliba.o -a kernel/kliba.s
Traps.o:kernel/Traps.c
	gcc -Iinclude -c -o Traps.o kernel/Traps.c
main.o: init/main.c
	gcc -Iinclude -c -o main.o init/main.c

	
system:	head.o kliba.o main.o asm.o Traps.o
	$(LD) $(LDFLAGS) -o system head.o kliba.o main.o asm.o Traps.o
clean:
	rm -f  Image setup bootsect system *.o *.s



 

你可能感兴趣的:(操作系统)