用C语言实现一个操作系统雏形SnailOS 0.00

还是效果图了,程序的结构很糟糕了,大家还是凑合着看吧!这个程序至少有两处BUG,不过好在我要求不高,现在能运行就行了。说是C语言,其实一些关键的地方或者说是不会用C的地方,还是不得不使用了汇编语言。

百度网盘下载地址:

https://pan.baidu.com/s/1_-IznMWL3z1CROziiD6mCw

#Makefile
CC=gcc
AS=as
LD=ld
OBJ = boot.o kernel.o

all: kernel

.S.o:
	$(AS) -o $@ $<
.c.o:
	$(CC) -c -o $@ $<

kernel: $(OBJ)
	$(LD) -Ttext 0x100000 -o $@ $^

default:	
	make all
	objcopy -I pe-i386 -O elf32-i386 kernel
	winimage ..\mybochs\andows.img kernel /i /h /y
 
run: 
	make default
	bochs -q -f ..\mybochs\bochsrc.bxrc
clean:
	del boot.o
	del kernel.o
	del kernel
	del ..\mybochs\*.lock
	del bochsout.txt
#boot.S
MULTIBOOT2_HEADER_MAGIC = 0xe85250d6
GRUB_MULTIBOOT_ARCHITECTURE_I386 = 0x0
MULTIBOOT_HEADER_TAG_ADDRESS = 0x2
MULTIBOOT_HEADER_TAG_OPTIONAL = 0x1
MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS = 0x3
MULTIBOOT_HEADER_TAG_END = 0x0
MULTIBOOT_HEADER_TAG_FRAMEBUFFER = 0x5

.globl _start

_start:
#跳转到程序的入口
	jmp multiboot_entry
#8字节对齐	
.align 8
multiboot_header:
#引导头的魔数0xe85250d6
	.int MULTIBOOT2_HEADER_MAGIC
#0是32保护模式i386
	.int GRUB_MULTIBOOT_ARCHITECTURE_I386
#引导头的字节长度
	.int multiboot_header_end - multiboot_header
#校验码
	.int -(MULTIBOOT2_HEADER_MAGIC + GRUB_MULTIBOOT_ARCHITECTURE_I386 + (multiboot_header_end - multiboot_header))

.align 8	
#应该叫做引导头的地址域(这或许不是必须存在的域)
address_tag_start:
	.short MULTIBOOT_HEADER_TAG_ADDRESS
	.short MULTIBOOT_HEADER_TAG_OPTIONAL
	.int address_tag_end - address_tag_start
	.int multiboot_header
	.int _start
	.int 0x0
	.int 0x0
address_tag_end:

.align 8
#应该叫做引导头入口的地址域(这或许不是必须存在的域)
entry_address_tag_start:
	.short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
	.short MULTIBOOT_HEADER_TAG_OPTIONAL
	.int entry_address_tag_end - entry_address_tag_start
	.int multiboot_entry
entry_address_tag_end:

.align 8
#帧缓冲的域(这或许不是必须存在的域,由这里可以进入预制的图形模式)
//framebuffer_tag_start:
//	.short MULTIBOOT_HEADER_TAG_FRAMEBUFFER
//	.short MULTIBOOT_HEADER_TAG_OPTIONAL
//	.int framebuffer_tag_end - framebuffer_tag_start
//	.int 800
//	.int 600
//	.int 16
//framebuffer_tag_end:

.align 8
#这个域在示例程序中未注明,所以我定义成了未定义的域。
undefined_tag:
	.short MULTIBOOT_HEADER_TAG_END
	.short 0
	.int 8
	
multiboot_header_end:

.align 8
#上面是能被grub2引导的符合multiboot标准的ELF格式文件。
#接下来即是我们的汇编代码,从这里我们可以调用C语言程序,
#从而摆脱汇编的束缚,当然也可以在这段代码之后定义无数的有用的汇编例程,
#供我们今后在C语言中调用,当然我们的原则是无法用C语言完成的,
#才会定义在这段代码之后。
multiboot_entry:
#关闭中断、初始化堆栈指针、清标志寄存器。
	cli
	movl $stack, %esp
	pushl $0
	popf

#为调用的C语言函数准备两个参数。	

	pushl %ebx
	pushl %eax
	call _cmain
	addl $8, %esp
1:
	hlt
	jmp 1b

	
SYS_CS = 1 * 8
SYS_DS = 2 * 8
VIDEO = 4 * 8
.global _myjmp
_myjmp: #void myjmp(void);
	ljmp $SYS_CS, $_newstart
_newstart:
	movw $SYS_DS, %ax
	movw %ax, %ds
	movw %ax, %es
	movw %ax, %ss
	movw $VIDEO, %ax
	movw %ax, %gs
	ret

	
.globl _divide_error
.extern _do_divide_error
_divide_error: #void divide_error(void);
	pushl $_do_divide_error
no_error_code:
	xchgl %eax, (%esp)
	pushl %ecx
	pushl %edx
	pushl %ebx
	pushl %esi
	pushl %edi
	pushl %ebp
	push %ds
	push %es
	push %fs
	pushl $0
	lea (11 * 4)(%esp), %edx
	pushl %edx
	movl $(2 * 8), %edx
	movw %dx, %ds
	movw %dx, %es
	movw %dx, %fs
	call *%eax
	addl $(2 * 4), %esp
#	addl $2, (10 * 4)(%esp) 仔细思考这里偏移量为什么是(10 * 4)
	pop %fs
	pop %es
	pop %ds
	popl %ebp
	popl %edi
	popl %esi
	popl %ebx
	popl %edx
	popl %ecx
	popl %eax
	iret
	
.globl _general_protection
.extern _do_general_protection #void do_general_protection(long esp, long error_code);
_general_protection: #void general_protection(void);
	pushl $_do_general_protection
error_code:
	xchgl %eax, 4(%esp)
	xchgl %ebx, (%esp)
	pushl %ecx
	pushl %edx
	pushl %edi
	pushl %esi
	pushl %ebp
	push %ds
	push %es
	push %fs
	pushl %eax
	lea 44(%esp), %eax
	pushl %eax
	movl $(2 * 8), %eax
	movw %ax, %ds
	movw %ax, %es
	movw %ax, %fs
	call *%ebx
	addl $8, %esp
	pop %fs
	pop %es
	pop %ds
	popl %ebp
	popl %esi
	popl %edi
	popl %edx
	popl %ecx
	popl %ebx
	popl %eax
	iret
	
	
	
tmp:
	.int 0
tmp1:
	.int 0
.globl _timer_interrupt
.extern _do_timer, _signal _current, _mycurrent, _sig, _tss_table, _myt
_timer_interrupt: #void timer_interrupt(void);
	pushal
	push %ds
	push %es
	push %fs
	movw $(2 * 8), %ax
	movw %ax, %ds
	call _do_timer

	movl (_mycurrent), %ebx
	movl (_current), %eax
	cmpl %ebx, %eax
	je 1f
	movl %eax, (tmp1)
	ljmp *(tmp)
1:
	movl $_tss_table + 4, %eax
	cmpl $0, _sig
	jne 2f
	movl $0, (%eax) 
2:
	cmpl $1, _sig
	jne 3f
	movl _myt, %ecx
	movl %ecx, (%eax)
3:
	pop %fs
	pop %es
	pop %ds
	popal
	iret	

.globl _key_interrupt
.extern _do_key
_key_interrupt: #void key_interrupt(void);
	pushal
	push %ds
	push %es
	push %fs
	movw $(2 * 8), %ax
	movw %ax, %ds
	call _do_key
	pop %fs
	pop %es
	pop %ds
	popal
	iret
	
.globl _sys_call
.extern _do_sys_call
_sys_call: #void sys_call(void);
	pushal
	push %ds
	push %es
	push %fs
	movw $(2 * 8), %dx
	movw %dx, %ds
	pushl %eax
	call _do_sys_call
	addl $(1 * 4), %esp
	pop %fs
	pop %es
	pop %ds
	popal
	iret
	
.globl _enable_timer_key
_enable_timer_key: #void enable_timer_key(void);
	movw $0x21, %dx
	inb %dx, %al
	andb $0xfc, %al
	outb %al, %dx
	ret
	
.globl _go_ring3
.extern _func0, _f0_u_s
_go_ring3: #void go_ring3(void);
	pushfl
	andl $0xffffbfff, (%esp)
	popfl
	movw $(5 * 8), %ax
	ltr %ax
	movw $(6 * 8), %ax
	lldt %ax
#	movw $(2 * 8 + 7), %ax
#	movw %ax, %ds
	sti
	pushl $(2 * 8 + 7)
	pushl %esp
	pushfl
	pushl $(1 * 8 + 7)
	pushl $(_func0)
	iret



#对齐4k边界
.align 0x1000
#预留16k空间	
.fill 0x4000, 1, 0
#栈顶
stack:




//kernel.c
#define switch_to(tss_sel) ({ \
struct {long a, b;} __tmp; \
__asm__("movw %%ax, %1\n\t" \
	"movl $0, %0\n\t" \
	"ljmp *%0" \
	::"m"(*&__tmp.a),"m"(*&__tmp.b), \
	"a"(tss_sel)); \
})

typedef struct descriptor {
	short limit_low;
	short base_low;
	char base_mid;
	char access_right;
	char limit_high;
	char base_high;
}descriptor, *Descriptor;

typedef struct gate {
	short offset_low;
	short selector;
	char dw_count;
	char access_right;
	short offset_high;
}gate, *Gate;

void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib) {
	if(limit > 0xfffff) {
		attrib |= 0x8000;
		limit /= 0x1000;
	}
	sd->limit_low = limit & 0xffff;
	sd->base_low = base & 0xffff;
	sd->base_mid = (base >> 16) & 0xff;
	sd->access_right = attrib & 0xff;
	sd->limit_high = ((limit >> 16) & 0x0f) | ((attrib >> 8) & 0xf0);
	sd->base_high = (base >> 24) & 0xff;
	return;
}

void set_gate(Gate gd, int offset, int selector, int attrib) {
	gd->offset_low = offset & 0xffff;
	gd->selector = selector;
	gd->dw_count = (attrib >> 8) & 0xff;
	gd->access_right = attrib & 0xff;
	gd->offset_high = (offset >> 16) & 0xffff;
	return;
}

typedef struct desc_struct {
	unsigned char ch[8];
}desc, *Desc;

typedef struct tss {
	int backlink;
	int esp0;
	int ss0;
	int esp1;
	int ss1;
	int esp2;
	int ss2;
	int cr3;
	int eip;
	int eflags;
	int eax;
	int ecx;
	int edx;
	int ebx;
	int esp;
	int ebp;
	int esi;
	int edi;
	int es;
	int cs;
	int ss;
	int ds;
	int fs;
	int gs;
	int ldt_sel;
	int trace_bitmap;
}tss, *Tss;

typedef struct ldt_tss_struct {
	desc myldt[6];
	tss mytss;
}ldt_tss, *Ldt_tss;

typedef union task_struct {
	ldt_tss myldt_tss;
	unsigned char ch[512];
}task, *Task;

task mytask[3];

Tss tss_table[3] = {&(mytask[0].myldt_tss.mytss), 
	&(mytask[1].myldt_tss.mytss), 
	&(mytask[2].myldt_tss.mytss)};

Tss myt = &(mytask[1].myldt_tss.mytss);
	
unsigned int current = 5 * 8 + 7;

void enable_timer_key(void);

#define move_to_user_mode() \
__asm__ ("movl %%esp,%%eax\n\t" \
	"pushl $0x17\n\t" \
	"pushl %%eax\n\t" \
	"pushfl\n\t" \
	"pushl $0x0f\n\t" \
	"pushl $1f\n\t" \
	"iret\n" \
	"1:\tmovl $0x17,%%eax\n\t" \
	"mov %%ax,%%ds\n\t" \
	"mov %%ax,%%es\n\t" \
	"mov %%ax,%%fs\n\t" \
	"mov %%ax,%%gs" \
	::)

#define sti() __asm__ ("sti"::)
#define cli() __asm__ ("cli"::)
#define nop() __asm__ ("nop"::)

#define iret() __asm__ ("iret"::)

#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))

struct desc_struct *idt = (struct desc_struct *) 0;
	
#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)

#define set_system_gate(n,addr) \
	_set_gate(&idt[n],15,3,addr)

#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
	*((gate_addr)+1) = ((base) & 0xff000000) | \
		(((base) & 0x00ff0000)>>16) | \
		((limit) & 0xf0000) | \
		((dpl)<<13) | \
		(0x00408000) | \
		((type)<<8); \
	*(gate_addr) = (((base) & 0x0000ffff)<<16) | \
		((limit) & 0x0ffff); }

#define _set_tssldt_desc(n,addr,type) \
__asm__ ("movw $104,%1\n\t" \
	"movw %%ax,%2\n\t" \
	"rorl $16,%%eax\n\t" \
	"movb %%al,%3\n\t" \
	"movb $" type ",%4\n\t" \
	"movb $0x00,%5\n\t" \
	"movb %%ah,%6\n\t" \
	"rorl $16,%%eax" \
	::"a" (addr), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
	 "m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
	)

#define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x89")
#define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x82")


#define _lgdt(gdtr) \
__asm__( \
	"movw %0, %%ax;" \
	"movw %%ax, %1;" \
	"lgdt (%2)" \
	::"m"(*(gdtr)),"m"(*(gdtr + 2)),"b"(gdtr + 2) \
)

#define _lidt(idtr) \
__asm__( \
	"movw %0, %%ax;" \
	"movw %%ax, %1;" \
	"lidt (%2)" \
	::"m"(*(idtr)),"m"(*(idtr + 2)),"b"(idtr + 2) \
)

#define _sgdt(gdtr) \
__asm__( \
	"sgdt (%2);" \
	"movw %1, %%ax;" \
	"movw %%ax, %0" \
	::"m"(*(gdtr)),"m"(*(gdtr + 2)),"b"(gdtr + 2) \
)


#define _init_8259() ({ \
__asm__(" \
	mov $0x11, %%al; \
	out %%al, $0x20; \
	out %%al, $0xa0; \
	mov $0x20, %%al; \
	out %%al, $0x21; \
	mov $0x28, %%al; \
	out %%al, $0xa1; \
	mov $0x04, %%al; \
	out %%al, $0x21; \
	mov $0x02, %%al; \
	out %%al, $0xa1; \
	mov $0x01, %%al; \
	out %%al, $0x21; \
	out %%al, $0xa1; \
	mov $0xff, %%al; \
	out %%al, $0x21; \
	out %%al, $0xa1" \
	::); \
})


//定时器的初始化说起来就是一句话,它是告诉
//时钟的发生装置,多长时间发生一次中断,
//据说这个对系统的性能有着十分关键的作用,
//也就是说如果发生的频繁了,运行时间就全被
//时钟中断用去了,如果是频率比较低,那么你就
//进程特别的迟钝,不过我没有编代码尝试过,又是
//道听途说罢了。设置频率是100毫秒发生一次时钟
//中断,这些都是抄书了。

#define _init_8253() \
__asm__(" \
	movb $0x36, %%al; \
	movw $0x43, %%dx; \
	outb %%al, %%dx; \
	movw $11931, %%ax; \
	movw $0x40, %%dx; \
	outb %%al, %%dx; \
	movb %%ah, %%al; \
	outb %%al, %%dx" \
	:: \
)

#define irq_disable(irq) ({ \
__asm__ __volatile__(" \
	pushfl; \
	cli; \
	movb $1, %%ah; \
	rolb %%cl, %%ah;\
	cmpb $8, %%cl; \
	jae 2f; \
	1: \
	inb $0x21, %%al; \
	testb %%ah, %%al; \
	jnz 3f; \
	orb %%ah, %%al; \
	outb %%al, $0x21; \
	jmp 3f; \
	2: \
	inb $0xa1, %%al; \
	testb %%ah, %%al; \
	jnz 3f; \
	orb %%ah, %%al; \
	outb %%al, $0xa1; \
	3: \
	popfl" \
	::"c"(irq)); \
})

#define irq_enable(irq) ({ \
__asm__ __volatile__(" \
	pushfl; \
	cli; \
	movb $~1, %%ah; \
	rolb %%cl, %%ah; \
	cmpb $8, %%cl; \
	jae 2f; \
	1: \
	inb $0x21, %%al; \
	andb %%ah, %%al; \
	outb %%al, $0x21; \
	jmp 3f; \
	2: \
	inb $0xa1, %%al; \
	andb %%ah, %%al; \
	outb %%al, $0xa1; \
	3: \
	popfl" \
	::"c"(irq)); \
})

#define out_b(port, data) \
__asm__("outb %%al, %%dx\n\t" \
		"nop\n\t" \
		"nop" \
		::"d"(port),"a"(data) \
)

#define in_b(port) ({\
register unsigned int res; \
__asm__("inb %%dx, %%al\n\t" \
		"nop\n\t" \
		"nop" \
		:"=a"(res):"d"(port)); \
res; \
})

//#include "multiboot2.h"

/*  Macros. */

/*  Some screen stuff. */
/*  The number of columns. */
#define COLUMNS                 80
/*  The number of lines. */
#define LINES                   25
/*  The attribute of an character. */
//#define ATTRIBUTE               7
/*  The video memory address. */
#define VIDEO                   0xb8000

/*  Variables. */
/*  Save the X position. */
static int xpos;
/*  Save the Y position. */
static int ypos;
/*  Point to the video memory. */
static volatile unsigned char *video;

/*  Forward declarations. */
void cmain (unsigned long magic, unsigned long addr);
static void cls (void);
static void itoa (char *buf, int base, int d);
static void myputchar (int c, int attrib);
void myprintf (int attrib, const char *format, ...);

#define IDT 0
#define IDT_LEN (256 * 8 - 1)
#define GDT (256 * 8)
#define GDT_LEN (512 * 8 - 1)
void myjmp(void);
#define ljmp() \
__asm__( \
	"ljmp $(1 * 8), $new_start\n\t" \
	"new_start:\n\t" \
	"movw $(2 * 8), %%ax\n\t" \
	"movw %%ax, %%ds\n\t" \
	"movw %%ax, %%es\n\t" \
	"movw %%ax, %%ss\n\t" \
	"movw $(4 * 8), %%ax\n\t" \
	"movw %%ax, %%gs\n\t" \
	:: \
)

void divide_error(void);
void general_protection(void);
void timer_interrupt(void);
void key_interrupt(void);
void sys_call(void);
void init_tss(Task task);

void func0(void);
char f0_u_s[128];
void func1(void);
char f1_u_s[128];
void func2(void);
char f2_u_s[128];


void _init_desc(void);



#define goto_ring3(t, stack) ({ \
__asm__("pushfl\n\t" \
		"andl $0xffffbfff, (%%esp)\n\t" \
		"popfl\n\t" \
		"movw $(5 * 8), %%ax\n\t" \
		"ltr %%ax\n\t" \
		"movw $(6 * 8), %%ax\n\t" \
		"lldt %%ax\n\t" \
		"movw $(2 * 8 + 7), %%ax\n\t" \
		"movw %%ax, %%ds\n\t" \
		"sti\n\t" \
		"pushl $(2 * 8 + 7)\n\t" \
		"pushl %0\n\t" \
		"pushfl\n\t" \
		"pushl $(1 * 8 + 7)\n\t" \
		"pushl %1\n\t" \
		"iret\n\t" \
		::"S"(stack + 128 - 1),"D"(t)); \
})\

void go_ring3(void);

void cmain (unsigned long magic, unsigned long addr)
{
	cls();
	int i;
	for(i = 0; i < 26; i++)
		myprintf (0xf, "Hello, World!\n");
//	myprintf(0xc, "How are you!\n");
	_init_desc();
	
	int test = 0 / 0;
	myprintf(0xf, "How are you!\n");
	myprintf(0xd, "SnailOS is startring......\n");	
	_init_8259();
	_init_8253();
	irq_enable(0);
	irq_enable(1);
	init_tss(mytask);
	current = tss_table[0]->ldt_sel - 8;
//	enable_timer_key();
//	sti();
//	goto_ring3(func0, f0_u_s);
	go_ring3();
//	func0();
//	func1();
//	func2();
	while(1) {
//应该是运行不到这里的
	}
}

void _init_desc(void) {
	static unsigned int idtr[2] = {IDT_LEN, IDT};
	static unsigned int gdtr[2] = {GDT_LEN, GDT};	
	_lidt((char *)idtr);
	_lgdt((char *)gdtr);
	//_set_seg_desc(gate_addr,type,dpl,base,limit);
//	_set_seg_desc((unsigned int *)(GDT + 0 * 8), 0, 0, 0, 0); //空描述符
//	_set_seg_desc((unsigned int *)(GDT + 1 * 8), 0xc09a, 0, 0, 0xffffffff);
//	_set_seg_desc((unsigned int *)(GDT + 2 * 8), 0xc092, 0, 0, 0xffffffff);
//	_set_seg_desc((unsigned int *)(GDT + 3 * 8), 0xc09a, 0, 0x100000, 0xffffffff);
//	_set_seg_desc((unsigned int *)(GDT + 4 * 8), 0xc092, 0, 0xb8000, 0xffff);
	set_descriptor((Descriptor) (GDT) + 0, 0, 0, 0);
	set_descriptor((Descriptor) (GDT) + 1, 0xffffffff, 0, 0xc09a);
	set_descriptor((Descriptor) (GDT) + 2, 0xffffffff, 0, 0xc092);
	set_descriptor((Descriptor) (GDT) + 3, 0xffffffff, 0x100000, 0xc09a);
	set_descriptor((Descriptor) (GDT) + 4, 0xffffffff, 0xb8000, 0xc092);
	set_descriptor((Descriptor) (GDT) + 5, 0xffffffff, (int)&(mytask[0].myldt_tss.mytss), 0xc0e9);
	set_descriptor((Descriptor) (GDT) + 6, 0xffffffff, (int)(mytask[0].myldt_tss.myldt), 0xc0e2);
	set_descriptor((Descriptor) (GDT) + 7, 0xffffffff, (int)&(mytask[1].myldt_tss.mytss), 0xc0e9);
	set_descriptor((Descriptor) (GDT) + 8, 0xffffffff, (int)(mytask[1].myldt_tss.myldt), 0xc0e2);
	set_descriptor((Descriptor) (GDT) + 9, 0xffffffff, (int)&(mytask[2].myldt_tss.mytss), 0xc0e9);
	set_descriptor((Descriptor) (GDT) + 10, 0xffffffff, (int)(mytask[2].myldt_tss.myldt), 0xc0e2);
//	_set_seg_desc((unsigned int *)(GDT + 5 * 8), 0xc0e9, 0, (unsigned int)&(mytask[0].myldt_tss.mytss), 6 * 8 - 10);
//	_set_seg_desc((unsigned int *)(GDT + 6 * 8), 0xc0e2, 0, (unsigned int)&(mytask[0].myldt_tss.myldt[0]), sizeof(tss) - 1);
	set_descriptor((Descriptor) (&(mytask[0].myldt_tss.myldt[0])), 0, 0, 0); //0 * 8 + 7
	set_descriptor((Descriptor) (&(mytask[0].myldt_tss.myldt[1])), 0xffffffff, 0x0, 0xc0fa); //1 * 8 + 7
	set_descriptor((Descriptor) (&(mytask[0].myldt_tss.myldt[2])), 0xffffffff, 0x0, 0xc0f2); //2 * 8 + 7
	set_descriptor((Descriptor) (&(mytask[1].myldt_tss.myldt[0])), 0, 0, 0); //0 * 8 + 7
	set_descriptor((Descriptor) (&(mytask[1].myldt_tss.myldt[1])), 0xffffffff, 0x0, 0xc0fa); //1 * 8 + 7
	set_descriptor((Descriptor) (&(mytask[1].myldt_tss.myldt[2])), 0xffffffff, 0x0, 0xc0f2); //2 * 8 + 7
	set_descriptor((Descriptor) (&(mytask[2].myldt_tss.myldt[0])), 0, 0, 0); //0 * 8 + 7
	set_descriptor((Descriptor) (&(mytask[2].myldt_tss.myldt[1])), 0xffffffff, 0x0, 0xc0fa); //1 * 8 + 7
	set_descriptor((Descriptor) (&(mytask[2].myldt_tss.myldt[2])), 0xffffffff, 0x0, 0xc0f2); //2 * 8 + 7
//	_set_seg_desc((unsigned int *)&(mytask[0].myldt_tss.myldt[0]), 0, 0, 0, 0);
//	_set_seg_desc((unsigned int *)&(mytask[0].myldt_tss.myldt[1]), 0xc0fa, 0, 0, 0xffffffff);
//	_set_seg_desc((unsigned int *)&(mytask[0].myldt_tss.myldt[2]), 0xc0f2, 0, 0, 0xffffffff);
	ljmp();

//	myprintf(0xf , "\n");
//	myprintf(0xf , "\n");
//	myprintf(0xf , "\n");
//	char *t = (char *) &(mytask[0].myldt_tss.myldt[0]);
//	myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 0 * 8 + 4)), *((int *)((char *)(GDT) + 0 * 8 + 0)));
//	myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 1 * 8 + 4)), *((int *)((char *)(GDT) + 1 * 8 + 0)));
//	myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 2 * 8 + 4)), *((int *)((char *)(GDT) + 1 * 8 + 0)));	
//	myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 3 * 8 + 4)), *((int *)((char *)(GDT) + 3 * 8 + 0)));
//	myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 4 * 8 + 4)), *((int *)((char *)(GDT) + 4 * 8 + 0)));
//	myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 5 * 8 + 4)), *((int *)((char *)(GDT) + 5 * 8 + 0)));
//	myprintf(0xd , "0x%x--0x%x\n", *((int *)((char *)(GDT) + 6 * 8 + 4)), *((int *)((char *)(GDT) + 6 * 8 + 0)));
//	myprintf(0xe , "0x%x--0x%x\n", *((int *)((char *)(t) + 0 * 8 + 4)), *((int *)((char *)(t) + 0 * 8 + 0)));
//	myprintf(0xe , "0x%x--0x%x\n", *((int *)((char *)(t) + 1 * 8 + 4)), *((int *)((char *)(t) + 1 * 8 + 0)));
//	myprintf(0xe , "0x%x--0x%x\n", *((int *)((char *)(t) + 2 * 8 + 4)), *((int *)((char *)(t) + 1 * 8 + 0)));	
//	set_intr_gate(n,addr);
	set_trap_gate(0 , &divide_error);
	set_trap_gate(0xd , &general_protection);
	set_intr_gate(0x20, &timer_interrupt);
	set_intr_gate(0x21, &key_interrupt);
	set_system_gate(0x80, sys_call);
	return;
}

void do_divide_error(int ret_addr, int err_code) {
	myprintf(0xc, "DIVIDE_ERROR!...retaddr = 0x%x, err_code = 0x%x", ret_addr, err_code);
__asm__("addl $2, (14 * 4)(%%ebp)"::); //仔细思考这里的偏移量为什么是(14 * 4),而且是相对于ebp的。
//	while(1) {
//		
//	}
}

void do_general_protection(long esp, long error_code) {
	myprintf(0xc, "General protection!...esp = 0x%x, error_code = 0x%x", esp, error_code);	
	while(1) {
		
	}
}

Tss * temp = tss_table;
unsigned int mycurrent = 5 * 8 + 7;
void sche(void) {
	while(1) {
		temp++;
		if(!(*temp)) {
			continue;
		}
		if(temp >= tss_table + 3) {
			temp = tss_table;
			break;
		}
		break;
	}
	if(current == (*temp)->ldt_sel - 8) {
		mycurrent = current;
	} else {
		current = (*temp)->ldt_sel - 8;
	}
}

unsigned int sig = 2;

//这里想用C来发送终止进程,但不知道何种原因,不能改变进程表,因此改用汇编语言。
void signal(void) {
	if(sig = 0) {
		tss_table[1] = 0;
	}
	if(sig = 1) {
		tss_table[1] = &(mytask[1].myldt_tss.mytss);
	}
}

unsigned int jiffies = 0;
unsigned int count = 0;
unsigned int count1 = 0;
void do_timer(void) {
	jiffies++;
	if(!(jiffies % 30)) {
		count++;		
	}
	if(!(jiffies % 120)) {
		count1++;		
	}
	out_b(0x20, 0x20);
//	myprintf(0xf ,"TIMER!...");
	sche();
}




void do_sys_call(int eax) {
	int mycount = count;
	int mycount1 = count1;
	if(eax == 0) {
		myprintf(0x9, " BLUE! ");
	} else if(eax == 1) {
		myprintf(0xc, " RED! ");
	} else if(eax == 2) {
		myprintf(0xa, " GREEN! ");
	} else if(eax == 3) {
		while(count == mycount) {
			
		}
	}  else if(eax == 4) {
		while(count1 == mycount1) {
			
		}
	}
	return;
}

unsigned char mykey;

void do_key(void) {
	mykey = in_b(0x60);
	out_b(0x20, 0x20);
	if(mykey == 0x1)
		sig = 0;
	if(mykey == 0x3b)
		sig = 1;
	if(mykey == 0xe0) {
		
	} else if(mykey == 0xe1) {
		
	} else if((mykey & 0x80) != 0){
		
	} else {
		myprintf(0xe, " 0x%x ", mykey);
	}
}

void func0(void) {
__asm__("movw $(2 * 8 + 7), %%ax\n\tmovw %%ax, %%ds\n\t"::);
	while(1) {
		__asm__("int $0x80\n\t"::"a"(3));
		__asm__("int $0x80\n\t"::"a"(0));
	}
__asm__("1:\n\tjmp 1b"::);
}

void func1(void) {
__asm__("movw $(2 * 8 + 7), %%ax\n\tmovw %%ax, %%ds\n\t"::);
	while(1) {
		__asm__("int $0x80\n\t"::"a"(3));
		__asm__("int $0x80\n\t"::"a"(1));
	}
__asm__("1:\n\tjmp 1b"::);
}

void func2(void) {
__asm__("movw $(2 * 8 + 7), %%ax\n\tmovw %%ax, %%ds\n\t"::);
	while(1) {
		__asm__("int $0x80\n\t"::"a"(4));
		__asm__("int $0x80\n\t"::"a"(2));
	}
__asm__("1:\n\tjmp 1b"::);
}

void init_tss(Task task) {
	Tss mytss;
	mytss = &(task[0].myldt_tss.mytss);
	
	mytss->backlink = 0;
	mytss->esp0 = (int)((char *)(&(task[0])) + 512 - 1);
	mytss->ss0 = 2 * 8;
	mytss->esp1= 0;
	mytss->ss1 = 0;
	mytss->esp2 = 0;
	mytss->ss2 = 0;
	mytss->cr3 = 0;
	mytss->eip = (int) func0;
	mytss->eflags = 0x200;
	mytss->eax = 0;
	mytss->ecx = 0;
	mytss->edx = 0;
	mytss->ebx = 0;
	mytss->esp = (int)(f0_u_s + 128 - 1);
	mytss->ebp = 0;
	mytss->esi = 0;
	mytss->edi = 0;
	mytss->es = 2 * 8 + 7;
	mytss->cs = 1 * 8 + 7;
	mytss->ss = 2 * 8 + 7;
	mytss->ds = 2 * 8 + 7;
	mytss->fs = 2 * 8 + 7;
	mytss->gs = 2 * 8 + 7;
	mytss->ldt_sel = 6 * 8;
	mytss->trace_bitmap = 0x8000000;

	mytss = &(task[1].myldt_tss.mytss);
	
	mytss->backlink = 0;
	mytss->esp0 = (int)((char *)(&(task[1])) + 512 - 1);
	mytss->ss0 = 2 * 8;
	mytss->esp1= 0;
	mytss->ss1 = 0;
	mytss->esp2 = 0;
	mytss->ss2 = 0;
	mytss->cr3 = 0;
	mytss->eip = (int) func1;
	mytss->eflags = 0x200;
	mytss->eax = 0;
	mytss->ecx = 0;
	mytss->edx = 0;
	mytss->ebx = 0;
	mytss->esp = (int)(f1_u_s + 128 - 1);
	mytss->ebp = 0;
	mytss->esi = 0;
	mytss->edi = 0;
	mytss->es = 2 * 8 + 7;
	mytss->cs = 1 * 8 + 7;
	mytss->ss = 2 * 8 + 7;
	mytss->ds = 2 * 8 + 7;
	mytss->fs = 2 * 8 + 7;
	mytss->gs = 2 * 8 + 7;
	mytss->ldt_sel = 8 * 8;
	mytss->trace_bitmap = 0x8000000;

	mytss = &(task[2].myldt_tss.mytss);
	
	mytss->backlink = 0;
	mytss->esp0 = (int)((char *)(&(task[2])) + 512 - 1);
	mytss->ss0 = 2 * 8;
	mytss->esp1= 0;
	mytss->ss1 = 0;
	mytss->esp2 = 0;
	mytss->ss2 = 0;
	mytss->cr3 = 0;
	mytss->eip = (int) func2;
	mytss->eflags = 0x200;
	mytss->eax = 0;
	mytss->ecx = 0;
	mytss->edx = 0;
	mytss->ebx = 0;
	mytss->esp = (int)(f2_u_s + 128 - 1);
	mytss->ebp = 0;
	mytss->esi = 0;
	mytss->edi = 0;
	mytss->es = 2 * 8 + 7;
	mytss->cs = 1 * 8 + 7;
	mytss->ss = 2 * 8 + 7;
	mytss->ds = 2 * 8 + 7;
	mytss->fs = 2 * 8 + 7;
	mytss->gs = 2 * 8 + 7;
	mytss->ldt_sel = 10 * 8;
	mytss->trace_bitmap = 0x8000000;
	return;
}

/*  Clear the screen and initialize VIDEO, XPOS and YPOS. */
static void cls (void)
{
	int i;
	video = (unsigned char *) VIDEO;
	for (i = 0; i < COLUMNS * LINES * 2; i++)
		*(video + i) = 0;
	xpos = 0;
	ypos = 0;
}

/*  Convert the integer D to a string and save the string in BUF. If
BASE is equal to 'd', interpret that D is decimal, and if BASE is
equal to 'x', interpret that D is hexadecimal. */
static void itoa (char *buf, int base, int d)
{
	char *p = buf;
	char *p1, *p2;
	unsigned long ud = d;
	int divisor = 10;
	/*  If %d is specified and D is minus, put `-' in the head. */
	if (base == 'd' && d < 0)
	{
		*p++ = '-';
		buf++;
		ud = -d;
	}
	else if (base == 'x')
		divisor = 16;
	/*  Divide UD by DIVISOR until UD == 0. */
	do
	{
		int remainder = ud % divisor;
		*p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
	}
	while (ud /= divisor);
	/*  Terminate BUF. */
	*p = 0;
	/*  Reverse BUF. */
	p1 = buf;
	p2 = p - 1;
	while (p1 < p2)
	{
		char tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++;
		p2--;
	}
}

/*  Put the character C on the screen. */
static void myputchar (int c, int attrib)
{
	if (c == '\n' || c == '\r')
	{
newline:
		xpos = 0;
		ypos++;
		if (ypos >= LINES) {
			cls();
		}
		return;
	}
	*(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
	*(video + (xpos + ypos * COLUMNS) * 2 + 1) = attrib;
	xpos++;
	if (xpos >= COLUMNS)
		goto newline;
}

/*  Format a string and print it on the screen, just like the libc
function printf. */
void myprintf (int attrib, const char *format, ...)
{
	char **arg = (char **) &format;
	int c;
	char buf[20];
	arg++;
	while ((c = *format++) != 0)
	{
		if (c != '%')
			myputchar (c, attrib);
		else
		{
			char *p, *p2;
			int pad0 = 0, pad = 0;
			c = *format++;
			if (c == '0')
			{
				pad0 = 1;
				c = *format++;
			}
			if (c >= '0' && c <= '9')
			{
				pad = c - '0';
				c = *format++;
			}
			switch (c)
			{
			case 'd':
			case 'u':
			case 'x':
				itoa (buf, c, *((int *) arg++));
				p = buf;
				goto string;
				break;

			case 's':
				p = *arg++;
				if (! p)
					p = "(null)";

string:
				for (p2 = p; *p2; p2++);
				for (; p2 < p + pad; p2++)
					myputchar (pad0 ? '0' : ' ', attrib);
				while (*p)
				myputchar (*p++, attrib);
				break;

				default:
					myputchar (*((int *) arg++), attrib);
					break;
			}
		}
	}
}
发布了159 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_39410618/article/details/86588017