简单的加入了中断重入的代码,运行效果完全一样了

 boot.s

bits 32

section .text


_start:
	jmp mystart
align 8
header_start:
	dd 0xe85250d6
	dd 0x0
	dd header_end - header_start
	dd - (0xe85250d6 + 0x0 + (header_end - header_start))
	
add_tag_start:
	dw 0x2
	dw 0x0
	dd add_tag_end - add_tag_start
	dd header_start
	dd _start
	dd 0x0
	dd 0x0
add_tag_end:

entry_add_tag_start:
	dw 0x3
	dw 0x1
	dd entry_add_tag_end - entry_add_tag_start
	dd mystart
entry_add_tag_end:
align 8

;framebuffer_tag_start:
;	dw 0x5
;	dw 0x1
;	dd framebuffer_tag_end - framebuffer_tag_start
;	dd 800
;	dd 600
;	dd 16
;framebuffer_tag_end:
align 8

	dw 0x0
	dw 0x0
	dd 0x8
header_end:
align 8

bits 32
[section .text]
mystart:
	mov esp, _stack_start
	push 0
	popf
	cli	
	
	push ebx
	push eax
extern _kernel_main
	call _kernel_main
	add esp, 8

	jmp $
	
times 1024 dw 0
_stack_start:

times 1024 dw 0
_new_stack:

global _halt
_halt: ; void halt(void);
	hlt
	ret
	
	
global _delay
_delay: ;void delay(int count);
	push ecx
	mov ecx, [esp + 4 * 2]
next:
	loop next
	pop ecx
	ret

global _load_gdtr
_load_gdtr: ; void load_gdtr(int limit, int addr);
	mov ax, [esp + 4]
	mov [esp + 6], ax
	lgdt [esp + 6]
	
	jmp dword 0x8 : newstart
newstart:

	mov eax, 0x10
	mov ds, eax
	mov es, eax
	mov fs, eax
	mov gs, eax
	mov ss, eax

	ret

global _load_idtr
_load_idtr: ; void load_idtr(int limit, int addr);
	mov ax, [esp + 4]
	mov [esp + 6], ax
	lidt [esp + 6]
	ret
	
global _asm_inthandler_all
extern _inthandler_all
_asm_inthandler_all: ; void asm_inthandler_all(void);
	push es
	push ds
	pushad
	mov eax, esp
	push eax
	mov eax, ss
	mov ds, eax
	mov es, eax
	call _inthandler_all
	pop eax
	popad
	pop ds
	pop es
	iret
	
global _asm_inthandler_0xd
extern _inthandler_0xd
_asm_inthandler_0xd: ; void asm_inthandler_0xd(void);
	push es
	push ds
	pushad
	mov eax, esp
	push eax
	mov eax, ss
	mov ds, eax
	mov es, eax
	call _inthandler_0xd
	pop eax
	popad
	pop ds
	pop es
	iret
	
global _asm_inthandler_0x20
extern _inthandler_0x20, _p_proc_ready, _mytss, _k_reenter
_asm_inthandler_0x20: ; void asm_inthandler_0x20(void);
	sub esp, 4
	pushad
	push ds
	push es
	push fs
	push gs
	mov dx, ss
	mov ds, dx
	mov es, dx
	
	mov al, 0x20
	out 0x20, al
	
	inc dword [_k_reenter]
	cmp dword [_k_reenter], 0
	jne .re_enter
	
	mov esp, _new_stack
	
	sti
	
	call _inthandler_0x20
	
	cli
	
	mov esp, [_p_proc_ready]
	lldt [esp + 72]
	lea eax, [esp + 72]
	mov [_mytss + 4], eax

.re_enter:
	dec dword [_k_reenter]
	pop gs
	pop fs
	pop es
	pop ds
	popad
	add esp, 4

	iretd
	
global _asm_inthandler_0x21
extern _inthandler_0x21
_asm_inthandler_0x21: ; void asm_inthandler_0x21(void);
	sub esp, 4
	pushad
	push ds
	push es
	push fs
	push gs
	mov dx, ss
	mov ds, dx
	mov es, dx
	
	mov esp, _new_stack
	
	call _inthandler_0x21
	
	mov esp, [_p_proc_ready]
	lldt [esp + 72]
	lea eax, [esp + 72]
	mov [_mytss + 4], eax
	
	pop gs
	pop fs
	pop es
	pop ds
	popad
	add esp, 4

	iretd

global _ud2
_ud2: ; void ud2(void);
	ud2
	ret
	
global _sti
_sti: ; void sti(void);
	sti
	ret

global _cli	
_cli: ; void cli(void);
	cli
	ret

global _init_8259a
_init_8259a:
	mov al, 0x11
	out 0x20, al
	nop
	out 0xa0, al
	nop
	mov al, 0x20
	out 0x21, al
	nop
	mov al, 0x28
	out 0xa1, al
	nop
	mov al, 0x04
	out 0x21, al
	nop
	mov al, 0x02
	out 0xa1, al
	nop
	mov al, 0x01
	out 0x21, al
	nop
	out 0xa1, al
	nop
	mov al, 0xff
	out 0x21, al
	nop
	out 0xa1, al
	nop
	ret	

global _out
_out: ; void out(int port, int value);
	mov edx, [esp + 1 * 4]
	mov eax, [esp + 2 * 4]
	out dx, al
	ret

global _in	
_in: ; unsigned char in(int port);
	mov edx, [esp + 1 * 4]
	xor eax, eax
	in al, dx
	ret
	
global _goto_ring3
extern _p_proc_ready, _mytss
_goto_ring3: ; void goto_ring3(void);
	mov esp, [_p_proc_ready]
	lldt [esp + 72]
	lea eax, [esp + 72]
	mov [_mytss + 4], eax
	
	pop gs
	pop fs
	pop es
	pop ds
	popad
	add esp, 4
	iretd

global _ltr	
_ltr: ; void ltr(short tr);
	mov ax, [esp + 4]
	ltr ax
	ret

 kernel.s


int k_reenter = -1;
// Descriptor

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;

// start process data struct

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;
	short trap;
	short iobase;
}tss, *Tss;

typedef struct proc_stack {
	int gs;
	int fs;
	int es;
	int ds;
	int edi;
	int esi;
	int ebp;
	int kernel_esp;
	int ebx;
	int edx;
	int ecx;
	int eax;
	int retaddr;
	int eip;
	int cs;
	int eflags;
	int esp;
	int ss;
}proc_stack;

typedef struct process {
	proc_stack procstack;
	
	short ldt_selector;
	descriptor ldt[0x10];
	int pid;
	char name[32];
}process, *Process;

// end process data struct


void print_s(char *str, char color, int j);
void halt(void);

void delay(int count);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);
void asm_inthandler_all(void);
void asm_inthandler_0xd(void);
void asm_inthandler_0x20(void);
void asm_inthandler_0x21(void);
void ud2(void);

void testa(void);
void testb(void);
void testc(void);
void testd(void);
void teste(void);
void testf(void);
void testg(void);
void testh(void);

void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib);
void set_gate(Gate gd, int offset, int selector, int attrib);

// S:copy from multiboot2 os example.
#define COLUMNS 80
#define LINES 24
#define ATTRIBUTE 7
#define VIDEO 0xb8000
     
static int xpos;
static int ypos;
static volatile unsigned char *video;
     
static void cls (void);
static void itoa (char *buf, int base, int d);
static void putchar (int c);
void printf (const char *format, ...);


void out(int port, int value);
int in(int port);
void sti(void);
void cli(void);
void init_8259a(void);
void init_8254(void);

int mycount = 0;

char *func_stack = (char *)0x800000;

process p_proc[8];
Process p_proc_ready, myproc;
tss tss0;
Tss mytss = &tss0;


typedef void (*task_f) (void);

typedef struct s_task {
	task_f initial_eip;
	int stacksize;
	char name[0x20];
}task, *Task;

task task_table[8] = {{testa, 0x400, "testa"}, \
					  {testb, 0x400, "testb"}, \
					  {testc, 0x400, "testc"}, \
					  {testd, 0x400, "testd"}, \
					  {teste, 0x400, "teste"}, \
					  {testf, 0x400, "testf"}, \
					  {testg, 0x400, "testg"}, \
					  {testh, 0x400, "testh"}};
					  

void goto_ring3(void);
void ltr(int tr);
void init_tss(Tss mytss, Descriptor mygdt);
void init_proc_table(Process myproc, Task mytask, Descriptor mygdt);

int kernel_main(int eax, int ebx) {
	cls();	
	
	Process myproc;
	myproc = p_proc;
	
	Descriptor mygdt = (Descriptor) 0x7c00;
	Gate myidt = (Gate) 0x0;
	set_descriptor(mygdt + 0, 0, 0, 0); //0 * 8
	set_descriptor(mygdt + 1, 0xffffffff, 0x0, 0xc09a); //1 * 8
	set_descriptor(mygdt + 2, 0xffffffff, 0x0, 0xc092); //2 * 8
	load_idtr(256 * 8 - 1, (int) myidt);
	load_gdtr(256 * 8 - 1, (int) mygdt);
	
	Task p_task = task_table;
	init_proc_table(myproc, p_task, mygdt);
	int i;

	for(i = 0; i < 256; i++) {
		set_gate(myidt + i, (int) asm_inthandler_all, 0x8, 0x8e);
	}
	set_gate(myidt + 0xd, (int) asm_inthandler_0xd, 0x8, 0x8e);	
	set_gate(myidt + 0x20, (int) asm_inthandler_0x20, 1 * 8, 0x8e);
	set_gate(myidt + 0x21, (int) asm_inthandler_0x21, 1 * 8, 0x8e);
//	set_gate(myidt + 0x80, (int) system_interrupt, 1 * 8, 0xee);


	init_tss(mytss, mygdt);
	
	init_8259a();
	init_8254();
	
	out(0x21, 0xf8);
	out(0xa1, 0xff);
	p_proc_ready = p_proc;
	goto_ring3();
	
	
	while(1) {
//			print_s("Sys!", 0xf, 17);
	}
	return 0;
}

void print_s(char *str, char color, int j) {
	int i = 0;
	while(*str) {
		while(*str == '\n') {
			str++;
			i = 0;
			j++;
		}
		if(!(*str)) {
			return;
		}
		*(video + i + j * 80 * 2) = *str++;
		*(video + i + 1 + j * 80 * 2) = color;
		i += 2;
	}
	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;
	return;
}
     
/*  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 putchar (int c) {
	if (c == '\n' || c == '\r') {
newline:
		xpos = 0;
		ypos++;
		if (ypos >= LINES)
			ypos = 0;
		return;
	}

	*(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
	*(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;

	xpos++;
	if (xpos >= COLUMNS)
		goto newline;
}
     
/*  Format a string and print it on the screen, just like the libc
function printf. */
void printf (const char *format, ...) {
	char **arg = (char **) &format;
	int c;
	char buf[20];
	arg++;

	while ((c = *format++) != 0) {
		if (c != '%')
			putchar (c);
		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++)
					putchar (pad0 ? '0' : ' ');
					while (*p)
					putchar (*p++);
					break;
				default:
					putchar (*((int *) arg++));
					break;
			}
		}
	}
}

void *memcpy(void *dest, void *source, int count) {
	int i;
	void *temp = dest;
	for(i = 0; i < count; i++) {
		 *((char *)dest++) = *((char *)source++);
	}
	return temp;
}

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;
}

void inthandler_all(int *esp) {
	printf("Exception! 0x%x", esp);
	while(1) {
		halt();
	}
	return;
}

void inthandler_0xd(int *esp) {
	printf("general protection! 0x%x", esp);
	while(1) {
		halt();
	}
	return;
}


void inthandler_0x20(int *esp) {
	char buf[0x40];
	print_s("timer interrupt!", 0xc, 23);
	itoa(buf, 10, mycount++);
	print_s(buf, 0xc, 24);
	p_proc_ready++;
	if (p_proc_ready >= p_proc + 8) {
		p_proc_ready = p_proc;
	}
	return;
}

void inthandler_0x21(int *esp) {
	out(0x20, 0x61);
	int key = in(0x60);
	char buf[0x40];
	print_s("keyboard interrupt!", 0xf, 21);
	print_s("     ", 0xf, 22);
	itoa(buf, 10, key);
	print_s(buf, 0xf, 22);
	return;
}


int ia = 0;
void testa(void) {
	char buf[0x20];
	while (1) {
		print_s("testa", 0x9, 0);
		itoa(buf, 10, ia++);
		print_s(buf, 0x9, 1);
		delay(0xfffff);
	}
	return;
}

int ib = 0;
void testb(void) {
	char buf[0x20];
	while (1) {
		print_s("testb", 0xd, 2);
		itoa(buf, 10, ib++);
		print_s(buf, 0xd, 3);
		delay(0xfff);
	}
	return;
}

int ic = 0;
void testc(void) {
	char buf[0x20];
	while (1) {
		print_s("testc", 0xf, 4);
		itoa(buf, 10, ic++);
		print_s(buf, 0xf, 5);
		delay(0x888);
	}
	return;
}

int id = 0;
void testd(void) {
	char buf[0x20];
	while (1) {
		print_s("testd", 0xe, 6);
		itoa(buf, 10, id++);
		print_s(buf, 0xe, 7);
		delay(0x88);

	}
	return;
}

int ie = 0;
void teste(void) {
	char buf[0x20];
	while (1) {
		print_s("teste", 0x4, 8);
		itoa(buf, 10, ie++);
		print_s(buf, 0x4, 9);
		delay(0xffff);

	}
	return;
}

int iff = 0;
void testf(void) {
	char buf[0x20];
	while (1) {
		print_s("testf", 0x8, 10);
		itoa(buf, 10, iff++);
		print_s(buf, 0x8, 11);
		delay(0xf);

	}
	return;
}

int ig = 0;
void testg(void) {
	char buf[0x20];
	while (1) {
		print_s("testg", 0x6, 12);
		itoa(buf, 10, ig++);
		print_s(buf, 0x6, 13);
		delay(0xaaaaa);

	}
	return;
}

int ih = 0;
void testh(void) {
	char buf[0x20];
	while (1) {
		print_s("testh", 0x7, 14);
		itoa(buf, 10, ih++);
		print_s(buf, 0x7, 15);
		delay(0xccc);

	}
	return;
}



void init_8254(void) {
	out(0x43, 0x36);
	out(0x40, 0x9c);
	out(0x40, 0x2e);
	return;
}


void init_proc_table(Process myproc, Task mytask, Descriptor mygdt) {
	int i;
	for(i = 0; i < 8; i++) {
		myproc->pid = i;
		myproc->ldt_selector = (3 + i) * 8;
		set_descriptor(mygdt + (3 + i), 8 * 0x10 - 1, (int)myproc->ldt, 0xc0e2);
		set_descriptor(myproc->ldt + 0, 0xffffffff, 0x0, 0xc0fa); //0 * 8 + 7
		set_descriptor(myproc->ldt + 1, 0xffffffff, 0x0, 0xc0f2); //1 * 8 + 7
		myproc->procstack.gs = 0xf;
		myproc->procstack.fs = 0xf;
		myproc->procstack.es = 0xf;
		myproc->procstack.ds = 0xf;	
		myproc->procstack.edi = 0x0;
		myproc->procstack.esi = 0x0;
		myproc->procstack.ebp = 0x0;
		myproc->procstack.kernel_esp = 0;	
		myproc->procstack.ebx = 0x0;
		myproc->procstack.edx = 0x0;
		myproc->procstack.ecx = 0x0;
		myproc->procstack.eax = 0x0;
		myproc->procstack.retaddr = 0x0;	
		myproc->procstack.eip = (int)mytask->initial_eip;
		myproc->procstack.cs = 0x7;
		myproc->procstack.eflags = 0x202;
		myproc->procstack.esp = (int)func_stack;
		myproc->procstack.ss = 0xf;
		
		myproc++;
		mytask++;
		func_stack -= 0x400;
	}
	return;
}

void init_tss(Tss mytss, Descriptor mygdt) {
	set_descriptor(mygdt + 20, sizeof(tss0), (int)mytss, 0xc0e9); //20 * 8
	mytss->backlink = 0;
	mytss->esp0 = 0;
	mytss->ss0 = 2 * 8;
	mytss->esp1= 0;
	mytss->ss1 = 0;
	mytss->esp2 = 0;
	mytss->ss2 = 0;
	mytss->cr3 = 0;
	mytss->eflags = 0;
	mytss->eax = 0;
	mytss->ecx = 0;
	mytss->edx = 0;
	mytss->esp = 0;
	mytss->ebp = 0;
	mytss->esi = 0;
	mytss->edi = 0;
	mytss->es = 0xf;
	mytss->cs = 0x7;
	mytss->ss = 0xf;
	mytss->ds = 0xf;
	mytss->fs = 0xf;
	mytss->gs = 0xf;
	mytss->ldt_sel = 0;
	mytss->trap = 0;
	mytss->iobase = sizeof(tss);
	ltr(20 * 8);
	return;
}

猜你喜欢

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