首次仿照《一個作業系統的實現》實現了ring0-ring3,為什麼這麼困難呢,開始懷疑程式生涯了
阿新 • • 發佈:2018-12-16
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