📄 main.c
字号:
/*============================================================================STRING.H C LIBRARY FUNCTIONS============================================================================*/#define NULL 0typedef unsigned size_t;/**********************************************************************************************************************************************************/void *memcpy(void *dst_ptr, const void *src_ptr, size_t count){ void *ret_val = dst_ptr; const char *src = (const char *)src_ptr; char *dst = (char *)dst_ptr;/* copy up */ for(; count != 0; count--) *dst++ = *src++; return ret_val;}/**********************************************************************************************************************************************************/void *memsetw(void *dst, int val, size_t count){ unsigned short *temp = (unsigned short *)dst; for( ; count != 0; count--) *temp++ = val; return dst;}/**********************************************************************************************************************************************************/size_t strlen(const char *str){ size_t ret_val; for(ret_val = 0; *str != '\0'; str++) ret_val++; return ret_val;}/*============================================================================STDARG.H C LIBRARY FUNCTIONS============================================================================*//* width of stack == width of int */#define STACKITEM inttypedef unsigned char *va_list;/* round up width of objects pushed on stack. The expression before the& ensures that we get 0 for objects of size 0. */#define VA_SIZE(TYPE) \ ((sizeof(TYPE) + sizeof(STACKITEM) - 1) \ & ~(sizeof(STACKITEM) - 1))/* &(LASTARG) points to the LEFTMOST argument of the function call(before the ...) */#define va_start(AP, LASTARG) \ (AP=((va_list)&(LASTARG) + VA_SIZE(LASTARG)))#define va_end(AP) /* nothing */#define va_arg(AP, TYPE) \ (AP += VA_SIZE(TYPE), *((TYPE *)(AP - VA_SIZE(TYPE))))/*============================================================================STDIO.H C LIBRARY FUNCTIONS============================================================================*//*****************************************************************************name: do_printfaction: minimal subfunction for ?printf, calls function 'fn' with arg 'ptr' for each character to be outputreturns:total number of characters outputnotes: does not handle long long (64-bit) values, far pointers, floats, precision part of field width, leading sign, or leading blanks.*****************************************************************************//* flags used in processing format string */#define PR_LJ 0x01 /* left justify */#define PR_CA 0x02 /* use A-F instead of a-f for hex */#define PR_SG 0x04 /* signed numeric conversion (%d vs. %u) */#define PR_32 0x08 /* long (32-bit) numeric conversion */#define PR_16 0x10 /* short (16-bit) numeric conversion */#define PR_WS 0x20 /* PR_SG set and num was < 0 */#define PR_LZ 0x40 /* pad left with '0' instead of ' ' */#define PR_FP 0x80 /* pointers are far *//* largest number handled is 2^32-1, lowest radix handled is 8.2^32-1 in base 8 has 11 digits (add 5 for trailing NUL and for slop) */#define PR_BUFLEN 16typedef int (*fnptr_t)(unsigned c, void **helper);int do_printf(const char *fmt, va_list args, fnptr_t fn, void *ptr){ unsigned state, flags, radix, actual_wd, count, given_wd; char *where, buf[PR_BUFLEN]; long num; state = flags = count = given_wd = 0;/* begin scanning format specifier list */ for(; *fmt; fmt++) { switch(state) {/* STATE 0: AWAITING % */ case 0: if(*fmt != '%') /* not %... */ { fn(*fmt, &ptr); /* ...just echo it */ count++; break; }/* found %, get next char and advance state to check if next char is a flag */ state++; fmt++; /* FALL THROUGH *//* STATE 1: AWAITING FLAGS (%-0) */ case 1: if(*fmt == '%') /* %% */ { fn(*fmt, &ptr); count++; state = flags = given_wd = 0; break; } if(*fmt == '-') { if(flags & PR_LJ)/* %-- is illegal */ state = flags = given_wd = 0; else flags |= PR_LJ; break; }/* not a flag char: advance state to check if it's field width */ state++;/* check now for '%0...' */ if(*fmt == '0') { flags |= PR_LZ; fmt++; } /* FALL THROUGH *//* STATE 2: AWAITING (NUMERIC) FIELD WIDTH */ case 2: if(*fmt >= '0' && *fmt <= '9') { given_wd = 10 * given_wd + (*fmt - '0'); break; }/* not field width: advance state to check if it's a modifier */ state++; /* FALL THROUGH *//* STATE 3: AWAITING MODIFIER CHARS (FNlh) */ case 3: if(*fmt == 'F') { flags |= PR_FP; break; } if(*fmt == 'N') break; if(*fmt == 'l') { flags |= PR_32; break; } if(*fmt == 'h') { flags |= PR_16; break; }/* not modifier: advance state to check if it's a conversion char */ state++; /* FALL THROUGH *//* STATE 4: AWAITING CONVERSION CHARS (Xxpndiuocs) */ case 4: where = buf + PR_BUFLEN - 1; *where = '\0'; switch(*fmt) { case 'X': flags |= PR_CA; /* FALL THROUGH *//* xxx - far pointers (%Fp, %Fn) not yet supported */ case 'x': case 'p': case 'n': radix = 16; goto DO_NUM; case 'd': case 'i': flags |= PR_SG; /* FALL THROUGH */ case 'u': radix = 10; goto DO_NUM; case 'o': radix = 8;/* load the value to be printed. l=long=32 bits: */DO_NUM: if(flags & PR_32) num = va_arg(args, unsigned long);/* h=short=16 bits (signed or unsigned) */ else if(flags & PR_16) { if(flags & PR_SG) num = va_arg(args, short); else num = va_arg(args, unsigned short); }/* no h nor l: sizeof(int) bits (signed or unsigned) */ else { if(flags & PR_SG) num = va_arg(args, int); else num = va_arg(args, unsigned int); }/* take care of sign */ if(flags & PR_SG) { if(num < 0) { flags |= PR_WS; num = -num; } }/* convert binary to octal/decimal/hex ASCIIOK, I found my mistake. The math here is _always_ unsigned */ do { unsigned long temp; temp = (unsigned long)num % radix; where--; if(temp < 10) *where = temp + '0'; else if(flags & PR_CA) *where = temp - 10 + 'A'; else *where = temp - 10 + 'a'; num = (unsigned long)num / radix; } while(num != 0); goto EMIT; case 'c':/* disallow pad-left-with-zeroes for %c */ flags &= ~PR_LZ; where--; *where = (char)va_arg(args, char); actual_wd = 1; goto EMIT2; case 's':/* disallow pad-left-with-zeroes for %s */ flags &= ~PR_LZ; where = va_arg(args, char *);EMIT: actual_wd = strlen(where); if(flags & PR_WS) actual_wd++;/* if we pad left with ZEROES, do the sign now */ if((flags & (PR_WS | PR_LZ)) == (PR_WS | PR_LZ)) { fn('-', &ptr); count++; }/* pad on left with spaces or zeroes (for right justify) */EMIT2: if((flags & PR_LJ) == 0) { while(given_wd > actual_wd) { fn(flags & PR_LZ ? '0' : ' ', &ptr); count++; given_wd--; } }/* if we pad left with SPACES, do the sign now */ if((flags & (PR_WS | PR_LZ)) == PR_WS) { fn('-', &ptr); count++; }/* emit string/char/converted number */ while(*where != '\0') { fn(*where++, &ptr); count++; }/* pad on right with spaces (for left justify) */ if(given_wd < actual_wd) given_wd = 0; else given_wd -= actual_wd; for(; given_wd; given_wd--) { fn(' ', &ptr); count++; } break; default: break; } default: state = flags = given_wd = 0; break; } } return count;}/*============================================================================X86.H C LIBRARY FUNCTIONS============================================================================*//**********************************************************************************************************************************************************/__inline__ unsigned inportb(unsigned port){ unsigned ret_val; __asm__ __volatile__("inb %w1,%b0" : "=a"(ret_val) : "d"(port)); return ret_val;}/**********************************************************************************************************************************************************/__inline__ void outportb(unsigned port, unsigned val){ __asm__ __volatile__("outb %b0,%w1" : : "a"(val), "d"(port));}/*============================================================================TEXT VIDEO ROUTINESEXPORTS:void putch(unsigned char c);void init_video(void);============================================================================*///#include <string.h> /* memcpy(), memsetw() *///#include <x86.h> /* outportb(), inportb() */#define VGA_MISC_READ 0x3CCstatic unsigned short *_vga_fb_adr;static unsigned _crtc_io_adr, _attrib, _csr_x, _csr_y, _vc_width, _vc_height;/**********************************************************************************************************************************************************/static void scroll(void){ unsigned blank, temp; blank = 0x20 | (_attrib << 8);/* scroll up */ if(_csr_y >= _vc_height) { temp = _csr_y - _vc_height + 1; memcpy(_vga_fb_adr, _vga_fb_adr + temp * _vc_width, (_vc_height - temp) * _vc_width);/* blank the bottom line of the screen */ memsetw(_vga_fb_adr + (_vc_height - temp) * _vc_width, blank, _vc_width); _csr_y = _vc_height - 1; }}/**********************************************************************************************************************************************************/static void move_csr(void){ unsigned temp; temp = _csr_y * _vc_width + _csr_x; outportb(_crtc_io_adr + 0, 14); outportb(_crtc_io_adr + 1, temp >> 8); outportb(_crtc_io_adr + 0, 15); outportb(_crtc_io_adr + 1, temp);}/**********************************************************************************************************************************************************/void putch(unsigned c){ unsigned att; att = _attrib << 8;/* backspace */ if(c == 0x08) { if(_csr_x != 0) _csr_x--; }/* tab */ else if(c == 0x09) _csr_x = (_csr_x + 8) & ~(8 - 1);/* carriage return */ else if(c == '\r') /* 0x0D */ _csr_x = 0;/* line feed */// else if(c == '\n') /* 0x0A */// _csr_y++;/* CR/LF */ else if(c == '\n') /* ### - 0x0A again */ { _csr_x = 0; _csr_y++; }/* printable ASCII */ else if(c >= ' ') { unsigned short *where; where = _vga_fb_adr + (_csr_y * _vc_width + _csr_x); *where = c | att; _csr_x++; } if(_csr_x >= _vc_width) { _csr_x = 0; _csr_y++; } scroll(); move_csr();}/**********************************************************************************************************************************************************/void init_video(void){/* check for monochrome or color VGA emulation */ if((inportb(VGA_MISC_READ) & 0x01) != 0) { _vga_fb_adr = (unsigned short *)0xB8000L; _crtc_io_adr = 0x3D4; } else { _vga_fb_adr = (unsigned short *)0xB0000L; _crtc_io_adr = 0x3B4; } _attrib = 0x30; /* black on cyan */ _vc_width = 80; _vc_height = 25;}/*============================================================================MAIN KERNEL CODEEXPORTS:extern unsigned long _virt_to_phys;void kprintf(const char *fmt, ...);int main(void);============================================================================*///#include <_printf.h> /* do_printf() *///#include <stdarg.h> /* va_list, va_start(), va_end() *//* IMPORTS: */void putch(unsigned c);void init_video(void);/**********************************************************************************************************************************************************/static int kprintf_help(unsigned c, void **ptr){ putch(c); return 0;}/**********************************************************************************************************************************************************/void kprintf(const char *fmt, ...){ va_list args; va_start(args, fmt); (void)do_printf(fmt, args, kprintf_help, NULL); va_end(args);}/*****************************************************************************for MinGW32*****************************************************************************/#ifdef __WIN32__#if __GNUC__<3#error Do not use MinGW GCC 2.x with NASM#endifint __main(void) { return 0; }void _alloca(void) { }#endif/**********************************************************************************************************************************************************/int main(void){ int score = 4, years; init_video(); kprintf("Hello from OSD 4\n"); years = -7; kprintf("%u score and %i years ago...\n", score, -years); kprintf("-1L == 0x%lX == octal %lo\n", -1L, -1L); kprintf("<%-08s> and <%08s> justified strings\n", "left", "right"); kprintf("Goodbye. Use reset button to end\n");/* return to KSTART.ASM, which will freeze */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -