1. 程式人生 > >首次仿照《一個作業系統的實現》實現了ring0-ring3,為什麼這麼困難呢,開始懷疑程式生涯了

首次仿照《一個作業系統的實現》實現了ring0-ring3,為什麼這麼困難呢,開始懷疑程式生涯了

 kernel.c


typedef char * va_list;

#ifdef  __cplusplus
#define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) )
#else
#define _ADDRESSOF(v)   ( &(v) )
#endif

#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap)      ( ap = (va_list)0 )

#define Test_va_start _crt_va_start 
#define Test_va_arg _crt_va_arg
#define Test_va_end _crt_va_end

#define ZEROPAD    1       
#define SIGN   2       
#define PLUS   4       
#define SPACE  8       
#define LEFT   16      
#define SPECIAL    32     
#define LARGE  64      

int _div(long* n,unsigned base);
static inline int isdigit(int ch);
static int skip_atoi(const char **s);
static char *Test_number(char *str, long num, int base, int size, int precision, int type);
int Test_vsprintf(char *buf, const char *fmt, va_list args);
int strnlen(const char * s, int precision);    
int sprintf(char *buf, const char *fmt, ...);


void fillbox(int color, int x0, int y0, int x1, int y1);
void myfillbox(int color, int x0, int y0, int x1, int y1);
void makefont16 (int color, int x, int y, short *font);
void print_gb2312(int color, int x, int y, unsigned char *str);

void delay(int count);
void *memcpy(void *dest, void *source, int count);


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 mypaint(unsigned int eax, unsigned int ebx);
void load_idtr(int limit, int addr);
void load_gdtr(int limit, int addr);
void set_descriptor(Descriptor sd, unsigned int limit, int base, int attrib);
void set_gate(Gate gd, int offset, int selector, int attrib);
void asm_inthandler_all(void);
void asm_inthandler_0xd(void);
//void inthandler_all(int *esp);
void ud2(void);


void func_a(void);
void func_b(void);

typedef struct mystack {
	char stack[0x200];
}mystack, *Mystack;

	
mystack func_stack[20];
char *func_a_stack;

void set_eflags(int value);
void goto_ring3(void);
void ltr(int tr);
void init_tss(Tss mytss);
void init_proc_table(Process myproc);

process p_proc[20];
Process p_proc_ready, myproc;
tss tss0;
Tss mytss;

char string[] = "系統宕機!";
int kernel_main (unsigned int eax, unsigned int ebx) {

	func_a_stack = (char *)(func_stack + 0x200);
	p_proc_ready = myproc = p_proc;
	mytss = &tss0;
	
	
	
	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
	set_descriptor(mygdt + 3, 8 * 0x10 - 1, (int)p_proc[0].ldt, 0xc0e2); //3 * 8
	set_descriptor(mygdt + 4, sizeof(tss0) - 1, (int)mytss, 0xc0e9); //4 * 8
	int k;
	for(k = 0; k < 256; k++) {
		set_gate(myidt + k, (int) asm_inthandler_all, 0x8, 0x8e);
	}
	set_gate(myidt + 0xd, (int) asm_inthandler_0xd, 0x8, 0x8e);
	load_idtr(256 * 8 - 1, (int) myidt);
	load_gdtr(256 * 8 - 1, (int) mygdt);
	mypaint(eax, ebx);
	
	set_eflags(0xffffbfff);
	init_tss(mytss);
	init_proc_table(p_proc_ready);

	ltr(4 * 8);
	goto_ring3();

//	int divzero = 2 / 0;
//	ud2();
	return -1;
}


void mypaint(unsigned int eax, unsigned int ebx) {
	fillbox(0x001e90ff, 0, 0, 799, 599);
	char buf[0x100], buf0[0x100];
	sprintf(buf, "eax = 0x%x ebx = 0x%x buf 的地址是 0x%x", eax, ebx, buf);
	print_gb2312(0xfffffff, 0, 0, buf);
	int i, j;
	for(i = 0; i < 400; i += 16) {
		fillbox(0xdddddddd, 16 + i, 16, 32 + i, 32);
		delay(0xffffff);
	}
	for(i = 0; i < 200; i += 16) {
		fillbox(0x88888888, 16 + i, 32, 32 + i, 48);
		delay(0xffffff);
	}
	for(i = 0; i < 100; i += 16) {
		fillbox(0x22222222, 16 + i, 48, 32 + i, 64);
		delay(0xffffff);
	}
	print_gb2312(0x00000000, 0, 568, (char *) memcpy(buf0, buf, 0x100));
	return;
}

	
void init_proc_table(Process myproc) {
	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)func_a;
	myproc->procstack.cs = 0x7;
//	myproc->procstack.eflags = 0x1202;
	myproc->procstack.esp = (int)func_a_stack;
	myproc->procstack.ss = 0xf;
	
	myproc->ldt_selector = 3 * 8;
	set_descriptor(myproc->ldt + 0, 0xffffffff, 0x0, 0xc0fa); //0 * 8 + 7
	set_descriptor(myproc->ldt + 1, 0xffffffff, 0x0, 0xc0f2); //1 * 8 + 7
}

void init_tss(Tss mytss) {
	mytss->backlink = 0;
	mytss->esp0 = 0;
	mytss->ss0 = 1 * 8;
	mytss->esp1= 0x0;
	mytss->ss1 = 0x0;
	mytss->esp2 = 0;
	mytss->ss2 = 0;
	mytss->cr3 = 0;
	mytss->eflags = 0x200;
	mytss->eax = 0;
	mytss->ecx = 0;
	mytss->edx = 0;
	mytss->esp = (int)func_a_stack;
	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 = 3 * 8;
	mytss->trap = 0;
	mytss->iobase = 0x8000;
}


void fillbox(int color, int x0, int y0, int x1, int y1) {
	int *myfb = (int *)0xe0000000;
	int xsize = 800;
	int x, y;
	for (y = 0; y <= y1 - y0; y++) {
		for (x = 0; x <= x1 - x0; x++) {
			myfb[x0 + x + (y0 + y) * xsize] = color;
		}
	}
}


void print_ascii (int color, int x, int y, char *font) {
	int *myfb = (int *)0xe0000000;
	int xsize = 800;
	char d;
	int *p;
	int i;
	for (i = 0; i < 16; i++){
		p = myfb + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) {p[0] = color;}
		if ((d & 0x40) != 0) {p[1] = color;}
		if ((d & 0x20) != 0) {p[2] = color;}
		if ((d & 0x10) != 0) {p[3] = color;}
		if ((d & 0x08) != 0) {p[4] = color;}
		if ((d & 0x04) != 0) {p[5] = color;}
		if ((d & 0x02) != 0) {p[6] = color;}
		if ((d & 0x01) != 0) {p[7] = color;}
	}
	return;
}

void makefont16 (int color, int x, int y, short *font) {
	int *myfb = (int *)0xe0000000;
	int xsize = 800;
	short d;
	int *p;
	int i;
	for (i = 0; i < 16; i++){
		p = myfb + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) {p[0] = color;}
		if ((d & 0x40) != 0) {p[1] = color;}
		if ((d & 0x20) != 0) {p[2] = color;}
		if ((d & 0x10) != 0) {p[3] = color;}
		if ((d & 0x08) != 0) {p[4] = color;}
		if ((d & 0x04) != 0) {p[5] = color;}
		if ((d & 0x02) != 0) {p[6] = color;}
		if ((d & 0x01) != 0) {p[7] = color;}
		if ((d & 0x8000) != 0) {p[8] = color;}
		if ((d & 0x4000) != 0) {p[9] = color;}
		if ((d & 0x2000) != 0) {p[10] = color;}
		if ((d & 0x1000) != 0) {p[11] = color;}
		if ((d & 0x800) != 0) {p[12] = color;}
		if ((d & 0x400) != 0) {p[13] = color;}
		if ((d & 0x200) != 0) {p[14] = color;}
		if ((d & 0x100) != 0) {p[15] = color;}
	}
	return;
}

void print_gb2312(int color, int x, int y, unsigned char *str) {
	extern short font[0x8000];
	extern char myfont[0x1000];
	int i = 0, j = 0;
	unsigned char a, b;
	unsigned int offset;
	while (str[i] != 0) {
		if (str[i] < 0x80) {
			a = str[i];
			print_ascii (color, x + j, y, myfont + a * 16);
			if (str[i + 1] == 0)
				break;
			i++;
			j += 8;
		} else {	
			a = str[i] - 0xa0;
			b = str[i + 1] - 0xa0;
			offset = ((a - 1) * 94 + (b - 1)) * 16;
			makefont16 (color, x + j , y, font + offset);
			i += 2;
			j += 16;
		}
	}
	return;
}



int sprintf(char *buf, const char *fmt, ...)
{
    va_list args;
    int val = 1;
    Test_va_start(args, fmt);
	Test_vsprintf(buf, fmt, args);
    Test_va_end(args);
    return val;
}



int _div(long* n,unsigned base)
{
     int __res; 
         __res = ((unsigned long) *n) % (unsigned) base; 
         *n = ((unsigned long) *n) / (unsigned) base; 
         return __res;
}

#define do_div(n,base)   _div(&n,base)


static inline int isdigit(int ch)
{
    return (ch >= '0') && (ch <= '9');
}

static int skip_atoi(const char **s)
{
    int i = 0;

    while (isdigit(**s))
        i = i * 10 + *((*s)++) - '0';
    return i;
}

static char *Test_number(char *str, long num, int base, int size, int precision, int type)
{
    char c, sign, tmp[66];
    const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
    int i;

    if (type & LARGE)
        digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    if (type & LEFT)
        type &= ~ZEROPAD;
    if (base < 2 || base > 36)
        return 0;
    c = (type & ZEROPAD) ? '0' : ' ';
    sign = 0;
    if (type & SIGN) {
        if (num < 0) {
            sign = '-';
            num = -num;
            size--;
        } else if (type & PLUS) {
            sign = '+';
            size--;
        } else if (type & SPACE) {
            sign = ' ';
            size--;
        }
    }
    if (type & SPECIAL) {
        if (base == 16)
            size -= 2;
        else if (base == 8)
            size--;
    }
    i = 0;
    if (num == 0)
    {
        tmp[i++] = '0';
    }
    else
    {
        while (num != 0)
        {
            tmp[i++] = digits[do_div(num, base)];
        }
    }

    if (i > precision)
        precision = i;
    size -= precision;
    if (!(type & (ZEROPAD + LEFT)))
        while (size-- > 0)
            *str++ = ' ';
    if (sign)
        *str++ = sign;
    if (type & SPECIAL) {
        if (base == 8)
            *str++ = '0';
        else if (base == 16) {
            *str++ = '0';
            *str++ = digits[33];
        }
    }
    if (!(type & LEFT))
        while (size-- > 0)
            *str++ = c;
    while (i < precision--)
        *str++ = '0';
    while (i-- > 0)
        *str++ = tmp[i];
    while (size-- > 0)
        *str++ = ' ';
    return str;
 }


int Test_vsprintf(char *buf, const char *fmt, va_list args)
{
    int len;
    unsigned long num;
    int i, base;
    char *str;
    const char *s;

    int flags;      

    int field_width;   
    int precision;    
    int qualifier;      

    for (str = buf; *fmt; ++fmt) {
        if (*fmt != '%') {
            *str++ = *fmt;
            continue;
        }


        flags = 0;
          repeat:
        ++fmt;      
        switch (*fmt) {
        case '-':
            flags |= LEFT;
            goto repeat;
        case '+':
            flags |= PLUS;
            goto repeat;
        case ' ':
            flags |= SPACE;
            goto repeat;
        case '#':
            flags |= SPECIAL;
            goto repeat;
        case '0':
            flags |= ZEROPAD;
            goto repeat;
        }


        field_width = -1;
        if (isdigit(*fmt))
            field_width = skip_atoi(&fmt);
        else if (*fmt == '*') {
            ++fmt;

            field_width = Test_va_arg(args, int);
            if (field_width < 0) {
                field_width = -field_width;
                flags |= LEFT;
            }
        }


        precision = -1;
        if (*fmt == '.') {
            ++fmt;
            if (isdigit(*fmt))
                precision = skip_atoi(&fmt);
            else if (*fmt == '*') {
                ++fmt;

                precision = Test_va_arg(args, int);
            }
            if (precision < 0)
                precision = 0;
        }


        qualifier = -1;
        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
            qualifier = *fmt;
            ++fmt;
        }


        base = 10;

        switch (*fmt) {
        case 'c':
            if (!(flags & LEFT))
                while (--field_width > 0)
                    *str++ = ' ';
            *str++ = (unsigned char)Test_va_arg(args, int);
            while (--field_width > 0)
                *str++ = ' ';
            continue;

        case 's':
            s = Test_va_arg(args, char *);
            len = strnlen(s, precision);

            if (!(flags & LEFT))
                while (len < field_width--)
                    *str++ = ' ';
            for (i = 0; i < len; ++i)
                *str++ = *s++;
            while (len < field_width--)
                *str++ = ' ';
            continue;

        case 'p':
            if (field_width == -1) {
                field_width = 2 * sizeof(void *);
                flags |= ZEROPAD;
            }
            str = Test_number(str,
                     (unsigned long)Test_va_arg(args, void *), 16,
                     field_width, precision, flags);
            continue;

        case 'n':
            if (qualifier == 'l') {
                long *ip = Test_va_arg(args, long *);
                *ip = (str - buf);
            } else {
                int *ip = Test_va_arg(args, int *);
                *ip = (str - buf);
            }
            continue;

        case '%':
            *str++ = '%';
            continue;

        case 'o':
            base = 8;
            break;

        case 'X':
            flags |= LARGE;
        case 'x':
            base = 16;
            break;

        case 'd':
        case 'i':
            flags |= SIGN;
        case 'u':
            break;

        default:
            *str++ = '%';
            if (*fmt)
                *str++ = *fmt;
            else
                --fmt;
            continue;
        }
        if (qualifier == 'l')
            num = Test_va_arg(args, unsigned long);
        else if (qualifier == 'h') {
            num = (unsigned short)Test_va_arg(args, int);
            if (flags & SIGN)
                num = (short)num;
        } else if (flags & SIGN)
            num = Test_va_arg(args, int);
        else
            num = Test_va_arg(args, unsigned int);
        str = Test_number(str, num, base, field_width, precision, flags);
    }
    *str = '\0';
    return str - buf;
}        

int strnlen(const char * s, int precision) {
	int len = 0;
	while (*s++ != 0) {
		len++;
	}
	return len;
}



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

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) {
	char buf[0x100];
	sprintf(buf, "發生了異常 0x%x", *esp);
	print_gb2312(0xffffffff, 400, 584, buf);
	return;
}

void inthandler_0xd(int *esp) {
	char buf[0x100];
	sprintf(buf, "發生通用保護異常 0x%x", *esp);
	print_gb2312(0xffffffff, 400, 552 - 32, buf);
	return;
}

void func_a(void) {
	char buf[0x100];
	int i = 0;
	while (1) {
		sprintf(buf, "我是程序A %d", i++);
		print_gb2312(0x00000000, 600, 0, buf);
		delay(0xffffff);
		fillbox(0x001e90ff, 600, 0, 600 + 128, 16);		
	}
	return;
}

void func_b(void) {
	char buf[0x100];
	int i = 0;
	while (1) {
		sprintf(buf, "我是程序B %d", i++);
		print_gb2312(0x00000000, 600, 0, buf);
		delay(0xffffff);
		fillbox(0x001e90ff, 600, 0 + 16, 600 + 128, 16 + 16);		
	}
	return;
}

boot.s

bits 32

section .text

global _start
extern _kernel_main, _print_gb2312, _string

_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 32
framebuffer_tag_end:
align 8

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

mystart:
	mov esp, _stack_start
	push 0
	popf
		
	push ebx
	push eax
	call _kernel_main
	add esp, 4 * 2

here:
	push _string
	push dword [y]
	push dword [x]
	push dword [color]
	call _print_gb2312
	add esp, 4 * 4
	hlt
	jmp here
	

y:	dd 584
x:	dd 0
color:
	dd 0x00ff0000

global _stack_start
times 0x1000 db 0
align 0x1000
_stack_start:


global _delay
_delay: ;void(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 _ud2
_ud2: ; void ud2(void);
	ud2
	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

global _set_eflags
_set_eflags: ; void set_eflags(int value);
	pushf
	mov eax, [esp + 8]
	and [esp + 0], eax
	popf
	ret

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

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