From 30bc6a618f5dd50c7bfdebb7646fb19d60844ece Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 13 Aug 2024 09:17:57 +0300 Subject: [PATCH] moving on --- kern/src/asmutil.asm | 54 ++++++++++++++++++++++++ kern/src/asmutil.h | 12 +++++- kern/src/dbg.c | 25 ++++++++++- kern/src/dbg.h | 2 +- kern/src/libc/ctype.c | 56 +++++++++++++++++++++++++ kern/src/libc/ctype.h | 17 ++++++++ kern/src/libc/limits.h | 19 +++++++++ kern/src/libc/stdio.c | 107 +++++++++++++++++++++++++++++++++++++++++++++--- kern/src/libc/stdio.h | 2 + kern/src/libc/stdlib.c | 69 +++++++++++++++++++++++++++++++ kern/src/libc/stdlib.h | 10 +++++ kern/src/main.c | 1 + 12 files changed, 365 insertions(+), 9 deletions(-) create mode 100644 kern/src/asmutil.asm create mode 100644 kern/src/libc/ctype.c create mode 100644 kern/src/libc/ctype.h create mode 100644 kern/src/libc/limits.h create mode 100644 kern/src/libc/stdlib.c create mode 100644 kern/src/libc/stdlib.h diff --git a/kern/src/asmutil.asm b/kern/src/asmutil.asm new file mode 100644 index 0000000..08c664e --- /dev/null +++ b/kern/src/asmutil.asm @@ -0,0 +1,54 @@ +; utility functions + cpu 8086 + bits 16 + section .text + + global getip +getip: push bp + mov bp, sp + mov ax, [bp + 2] + pop bp + ret + + global getregs +getregs: + push bp + mov bp, sp + + mov bp, [bp + 4] ; grab regs pointer + mov [bp], ax + mov [bp + 2], bx + mov [bp + 4], cx + mov [bp + 6], dx + mov ax, sp + add ax, 6 + mov [bp + 8], ax ; sp before the getregs call + mov bx, sp + mov ax, [bx] + mov [bp + 10], ax ; bp + mov [bp + 12], si + mov [bp + 14], di + pushf + pop ax + mov [bp + 16], ax ; cflags + mov ax, [bx + 2] ; caller ip + + pop bp + ret + + global getsregs +getsregs: + push bp + mov bp, sp + + mov ax, [bp + 4] + add ax, 8 ; point to the top of the sregs block (after ss) + mov sp, ax ; point sp there + push ss + push es + push ds + push cs + + mov sp, bp + pop bp + ret diff --git a/kern/src/asmutil.h b/kern/src/asmutil.h index 9d5697b..1720f5a 100644 --- a/kern/src/asmutil.h +++ b/kern/src/asmutil.h @@ -5,7 +5,9 @@ struct wordregs { uint16_t ax, bx, cx, dx; - uint16_t si, di, cflag; + uint16_t sp, bp; + uint16_t si, di, flags; + uint16_t ip; } __attribute__((packed)); struct byteregs { @@ -20,7 +22,14 @@ union regs { struct byteregs h; }; +struct segregs { + uint16_t cs, ds, es, ss; +} __attribute__((packed)); + void int86(int n, union regs *inregs, union regs *outregs); +uint16_t getip(void); +void getregs(struct wordregs *regs); +void getsregs(struct segregs *sregs); #define FP_SEG(x) ((uint16_t)((uint32_t)(x) >> 16)) #define FP_OFFS(x) ((uint16_t)(x)) @@ -28,6 +37,7 @@ void int86(int n, union regs *inregs, union regs *outregs); #define enable() asm("sti") #define disable() asm("cli") +#define halt() asm("hlt") #define outp(p, v) \ asm volatile( \ diff --git a/kern/src/dbg.c b/kern/src/dbg.c index ad4c57a..7daf689 100644 --- a/kern/src/dbg.c +++ b/kern/src/dbg.c @@ -1,6 +1,29 @@ -#include +#include +#include #include "dbg.h" +#include "asmutil.h" +__attribute__((noreturn)) void panic(const char *fmt, ...) { + va_list ap; + struct wordregs regs; + struct segregs sregs; + + getregs(®s); + regs.ip = getip(); /* replace ip with the caller's */ + getsregs(&sregs); + + printf("~~~~ PANIC ~~~~\n"); + + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + + printf("ax:%04x bx:%04x cx:%04x dx:%04x\n", regs.ax, regs.bx, regs.cx, regs.dx); + printf("bp:%04x si:%04x di:%04x flags:%04x\n", regs.bp, regs.si, regs.di, regs.flags); + printf("ss:sp %04x:%04x cs:ip %04x:%04x ds:%04x es:%04x\n", sregs.ss, regs.sp, + sregs.cs, regs.ip, sregs.ds, sregs.es); + + for(;;) halt(); } diff --git a/kern/src/dbg.h b/kern/src/dbg.h index acf7d3e..638f8ee 100644 --- a/kern/src/dbg.h +++ b/kern/src/dbg.h @@ -1,6 +1,6 @@ #ifndef DBG_H_ #define DBG_H_ -void panic(const char *fmt, ...); +void panic(const char *fmt, ...) __attribute__((noreturn)); #endif /* DBG_H_ */ diff --git a/kern/src/libc/ctype.c b/kern/src/libc/ctype.c new file mode 100644 index 0000000..82b7eb5 --- /dev/null +++ b/kern/src/libc/ctype.c @@ -0,0 +1,56 @@ +#include "ctype.h" + +int isalnum(int c) +{ + return isalpha(c) || isdigit(c); +} + +int isalpha(int c) +{ + return isupper(c) || islower(c); +} + +int isblank(int c) +{ + return c == ' ' || c == '\t'; +} + +int isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +int isupper(int c) +{ + return c >= 'A' && c <= 'Z'; +} + +int islower(int c) +{ + return c >= 'a' && c <= 'z'; +} + +int isgraph(int c) +{ + return c > ' ' && c <= '~'; +} + +int isprint(int c) +{ + return isgraph(c) || c == ' '; +} + +int isspace(int c) +{ + return isblank(c) || c == '\f' || c == '\n' || c == '\r' || c == '\v'; +} + +int toupper(int c) +{ + return c & ~0x20; +} + +int tolower(int c) +{ + return c | 0x20; +} diff --git a/kern/src/libc/ctype.h b/kern/src/libc/ctype.h new file mode 100644 index 0000000..5b010d4 --- /dev/null +++ b/kern/src/libc/ctype.h @@ -0,0 +1,17 @@ +#ifndef CTYPE_H_ +#define CTYPE_H_ + +int isalnum(int c); +int isalpha(int c); +#define isascii(c) ((c) < 128) +int isblank(int c); +int isdigit(int c); +int isupper(int c); +int islower(int c); +int isprint(int c); +int isspace(int c); + +int toupper(int c); +int tolower(int c); + +#endif /* CTYPE_H_ */ diff --git a/kern/src/libc/limits.h b/kern/src/libc/limits.h new file mode 100644 index 0000000..18d175d --- /dev/null +++ b/kern/src/libc/limits.h @@ -0,0 +1,19 @@ +#ifndef LIMITS_H_ +#define LIMITS_H_ + +#define CHAR_BIT 8 + +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 +#define INT_MIN (-32768) +#define INT_MAX 32767 +#define LONG_MIN (-2147483648) +#define LONG_MAX 2147483647 + +#define USHRT_MAX 65535 +#define UINT_MAX 65535 +#define ULONG_MAX 0xffffffff + +#define PATH_MAX 256 + +#endif /* LIMITS_H_ */ diff --git a/kern/src/libc/stdio.c b/kern/src/libc/stdio.c index 5c52d56..f2a9619 100644 --- a/kern/src/libc/stdio.c +++ b/kern/src/libc/stdio.c @@ -1,6 +1,8 @@ #include +#include #include #include +#include struct outbuf { char *buf; @@ -35,6 +37,11 @@ int printf(const char *fmt, ...) return res; } +int vprintf(const char *fmt, va_list ap) +{ + return intern_vprintf(0, fmt, ap); +} + static void reset_format(struct format *fmt) { memset(fmt, 0, sizeof *fmt); @@ -84,7 +91,7 @@ static int intern_vprintf(struct outbuf *outbuf, const char *fmtstr, va_list ap) } else { uval = va_arg(ap, unsigned int); } - count += wrint(outbuf, &fmt, uval); + count += wruint(outbuf, &fmt, uval); reset_format(&fmt); break; @@ -94,9 +101,17 @@ static int intern_vprintf(struct outbuf *outbuf, const char *fmtstr, va_list ap) reset_format(&fmt); break; + case '0': + if(fmt.fchar != '0') { + fmt.fchar = '0'; + break; + } default: - /* TODO: more format specifiers */ - reset_format(&fmt); + if(isdigit(c)) { + fmt.fwidth = strtol(fmtstr - 1, (char**)&fmtstr, 10); + } else { + reset_format(&fmt); + } break; } } @@ -123,7 +138,7 @@ static int wrstr(struct outbuf *outbuf, struct format *fmt, const char *s) if(fmt->flags & FMT_RALIGN) { len = strlen(s); - while(len-- < fmt->fwidth) { + while(len < fmt->fwidth--) { wrchar(outbuf, fmt->fchar); count++; } @@ -135,12 +150,92 @@ static int wrstr(struct outbuf *outbuf, struct format *fmt, const char *s) return count; } +static const char hexconv[] = "0123456789abcdef"; + static int wrint(struct outbuf *outbuf, struct format *fmt, long val) { - return 0; /* TODO */ + char buf[16], *ptr = buf + 15; + int neg = 0; + + buf[15] = 0; + + if(val < 0) { + neg = 1; + val = -val; + } + + if(val == 0) { + *ptr++ = '0'; + } + + switch(fmt->base) { + case 16: + while(val) { + *--ptr = hexconv[val & 0xf]; + val >>= 4; + } + break; + + case 8: + while(val) { + *--ptr = '0' | (val & 7); + val >>= 3; + } + break; + + default: /* assume 10 */ + /* + while(val) { + *--ptr = '0' | (val % 10); + val /= 10; + } + */ + break; + } + + if(neg) { + *--ptr = '-'; + } + fmt->flags |= FMT_RALIGN; + return wrstr(outbuf, fmt, ptr); } static int wruint(struct outbuf *outbuf, struct format *fmt, unsigned long val) { - return 0; /* TODO */ + static const char hexconv[] = "0123456789abcdef"; + char buf[16], *ptr = buf + 15; + + buf[15] = 0; + + if(val == 0) { + *ptr++ = '0'; + } + + switch(fmt->base) { + case 16: + while(val) { + *--ptr = hexconv[val & 0xf]; + val >>= 4; + } + break; + + case 8: + while(val) { + *--ptr = '0' | (val & 7); + val >>= 3; + } + break; + + default: /* assume 10 */ + /* + while(val) { + *--ptr = '0' | (val % 10); + val /= 10; + } + */ + break; + } + + fmt->flags |= FMT_RALIGN; + return wrstr(outbuf, fmt, ptr); } diff --git a/kern/src/libc/stdio.h b/kern/src/libc/stdio.h index 075715c..12388c5 100644 --- a/kern/src/libc/stdio.h +++ b/kern/src/libc/stdio.h @@ -1,10 +1,12 @@ #ifndef STDIO_H_ #define STDIO_H_ +#include #include "con.h" #define putchar(c) con_putchar(c) int printf(const char *fmt, ...); +int vprintf(const char *fmt, va_list ap); #endif /* STDIO_H_ */ diff --git a/kern/src/libc/stdlib.c b/kern/src/libc/stdlib.c new file mode 100644 index 0000000..b0ae8fb --- /dev/null +++ b/kern/src/libc/stdlib.c @@ -0,0 +1,69 @@ +#include +#include +#include + +int atoi(const char *str) +{ + return strtol(str, 0, 10); +} + +long atol(const char *str) +{ + return strtol(str, 0, 10); +} + +long strtol(const char *str, char **endp, int base) +{ + long acc = 0; + int sign = 1; + int valid = 0; + const char *start = str; + + while(isspace(*str)) str++; + + if(base == 0) { + if(str[0] == '0') { + if(str[1] == 'x' || str[1] == 'X') { + base = 16; + } else { + base = 8; + } + } else { + base = 10; + } + } + + if(*str == '+') { + str++; + } else if(*str == '-') { + sign = -1; + str++; + } + + while(*str) { + long val = LONG_MAX; + char c = tolower(*str); + + if(isdigit(c)) { + val = (int)*str & 0xf; + } else if(c >= 'a' && c <= 'f') { + val = 10 + c - 'a'; + } else { + break; + } + if(val >= base) { + break; + } + valid = 1; + + acc = acc * base + val; + str++; + } + + if(endp) { + *endp = (char*)(valid ? str : start); + } + + return sign > 0 ? acc : -acc; +} + diff --git a/kern/src/libc/stdlib.h b/kern/src/libc/stdlib.h new file mode 100644 index 0000000..f8ff71b --- /dev/null +++ b/kern/src/libc/stdlib.h @@ -0,0 +1,10 @@ +#ifndef STDLIB_H_ +#define STDLIB_H_ + +#define abs(x) __builtin_abs(x) + +int atoi(const char *str); +long atol(const char *str); +long strtol(const char *str, char **endp, int base); + +#endif /* STDLIB_H_ */ diff --git a/kern/src/main.c b/kern/src/main.c index b59e371..9022900 100644 --- a/kern/src/main.c +++ b/kern/src/main.c @@ -13,6 +13,7 @@ void kmain(void) con_init(); printf("eightysix kernel %s\n", VERSTR); + printf("foo: %04x\n", 0xabc); init_intr(); } -- 1.7.10.4