From 34ef535c1b94140ae0be569cbee4da9456a15e95 Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Fri, 18 Nov 2016 18:00:39 -0200 Subject: [PATCH 1/4] add idea concept 1 Signed-off-by: Tiago Natel de Moura --- xxx/Makefile | 17 +++++++++++++++++ xxx/include/types.h | 11 +++++++++++ xxx/main.c | 14 ++++++++++++++ xxx/regs.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 xxx/Makefile create mode 100644 xxx/include/types.h create mode 100644 xxx/main.c create mode 100644 xxx/regs.c diff --git a/xxx/Makefile b/xxx/Makefile new file mode 100644 index 0000000..d4f53d1 --- /dev/null +++ b/xxx/Makefile @@ -0,0 +1,17 @@ +TARGET = xxx + +all: clean $(TARGET) + +$(TARGET): + smlrcc main.c regs.c -I./include -o $(TARGET) + +debug: + gdb ./xxx \ + -ex "target remote localhost:1234" \ + -ex "set architecture i80386" \ + -ex "set disassembly-flavor intel" \ + -ex "layout asm" -ex "layout regs" \ + -ex "break *0x80490b0" + +clean: + rm -f $(TARGET) diff --git a/xxx/include/types.h b/xxx/include/types.h new file mode 100644 index 0000000..b4b297a --- /dev/null +++ b/xxx/include/types.h @@ -0,0 +1,11 @@ +/** + * common data types + */ + +typedef int32_t i32; +typedef int16_t i16; +typedef int8_t i8; + +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; diff --git a/xxx/main.c b/xxx/main.c new file mode 100644 index 0000000..e986b31 --- /dev/null +++ b/xxx/main.c @@ -0,0 +1,14 @@ +#include + +void printRegs() { + printf("eax=%08x\tesp=%08x\n", eax(), esp()); + printf("ebx=%08x\tebp=%08x\n", ebx(), ebp()); +} + +int main() { + printf("xxx v0.0.1\n"); + + printRegs(); + + return 0; +} diff --git a/xxx/regs.c b/xxx/regs.c new file mode 100644 index 0000000..e973624 --- /dev/null +++ b/xxx/regs.c @@ -0,0 +1,46 @@ +/** + * get register info + */ + +#include +#include "types.h" + +/* 32bit registers */ + +i32 eax() { + /* by calling convention */ +} + +i32 ebx() { + asm("mov eax, ebx"); +} + +i32 ecx() { + asm("mov eax, ecx"); +} + +i32 edx() { + asm("mov eax, edx"); +} + +i32 eip() { + asm("__geteip: mov eax, [esp]\n" + " ret\n" + "call __geteip"); +} + +i32 esp() { + asm("mov eax, esp"); +} + +i32 ebp() { + asm("mov eax, ebp"); +} + +i32 esi() { + asm("mov eax, esi"); +} + +i32 edi() { + asm("mov eax, edi"); +} From b7700644622b01a1bfda41f9a83a3a468f94135b Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Fri, 18 Nov 2016 18:10:30 -0200 Subject: [PATCH 2/4] fix debug rule of makefile Signed-off-by: Tiago Natel de Moura --- xxx/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xxx/Makefile b/xxx/Makefile index d4f53d1..39ae425 100644 --- a/xxx/Makefile +++ b/xxx/Makefile @@ -6,12 +6,12 @@ $(TARGET): smlrcc main.c regs.c -I./include -o $(TARGET) debug: - gdb ./xxx \ - -ex "target remote localhost:1234" \ - -ex "set architecture i80386" \ + gdb -ex "set architecture 386:386" \ -ex "set disassembly-flavor intel" \ -ex "layout asm" -ex "layout regs" \ - -ex "break *0x80490b0" + -ex "br *0x80490b0" \ + -ex "set startup-with-shell off" \ + ./xxx clean: rm -f $(TARGET) From 7ea3fb0c32adb346b08a7fb0911958df5fb77272 Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Fri, 18 Nov 2016 19:26:57 -0200 Subject: [PATCH 3/4] add reg data structure Signed-off-by: Tiago Natel de Moura --- xxx/dat.h | 23 ++++++++++++ xxx/fns.h | 4 +++ xxx/include/types.h | 11 ------ xxx/main.c | 14 ++++---- xxx/regs.c | 86 ++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 116 insertions(+), 22 deletions(-) create mode 100644 xxx/dat.h create mode 100644 xxx/fns.h delete mode 100644 xxx/include/types.h diff --git a/xxx/dat.h b/xxx/dat.h new file mode 100644 index 0000000..4f0abee --- /dev/null +++ b/xxx/dat.h @@ -0,0 +1,23 @@ +/** + * common data types + */ + +#include + +/* basic types */ +typedef int32_t i32; +typedef int16_t i16; +typedef int8_t i8; + +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +/* Reg hold processor registers */ +typedef struct { + i32 eax, ebx, ecx, edx; + i32 eip, ebp, esi, edi; + i32 esp; + + i16 cs, ds, es, fs, gs; +} Reg; diff --git a/xxx/fns.h b/xxx/fns.h new file mode 100644 index 0000000..cd73f94 --- /dev/null +++ b/xxx/fns.h @@ -0,0 +1,4 @@ +/** function definitions */ + +void printRegs32(Reg*); +void printRegs16(Reg*); diff --git a/xxx/include/types.h b/xxx/include/types.h deleted file mode 100644 index b4b297a..0000000 --- a/xxx/include/types.h +++ /dev/null @@ -1,11 +0,0 @@ -/** - * common data types - */ - -typedef int32_t i32; -typedef int16_t i16; -typedef int8_t i8; - -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; diff --git a/xxx/main.c b/xxx/main.c index e986b31..f16a9f9 100644 --- a/xxx/main.c +++ b/xxx/main.c @@ -1,14 +1,14 @@ #include - -void printRegs() { - printf("eax=%08x\tesp=%08x\n", eax(), esp()); - printf("ebx=%08x\tebp=%08x\n", ebx(), ebp()); -} +#include "dat.h" +#include "fns.h" int main() { - printf("xxx v0.0.1\n"); + Reg reg; + + newreg(®); - printRegs(); + printRegs32(®); + printRegs16(®); return 0; } diff --git a/xxx/regs.c b/xxx/regs.c index e973624..f316cc2 100644 --- a/xxx/regs.c +++ b/xxx/regs.c @@ -3,7 +3,49 @@ */ #include -#include "types.h" +#include "dat.h" + +#define LSW(r32) (r32 & 0xffff) /* least significant word */ +#define MSW(r32) (i16(r32 >> 4)) /* most significant word */ + +void newreg(Reg *reg) { + reg->eax = eax(); + reg->ebx = ebx(); + reg->ecx = ecx(); + reg->edx = edx(); + reg->eip = eip(); + reg->ebp = ebp(); + reg->esi = esi(); + reg->edi = edi(); + + reg->esp = esp(); + + reg->cs = cs(); + reg->ds = ds(); + reg->es = es(); + reg->fs = fs(); + reg->gs = gs(); +} + +void printRegs32(Reg *reg) { + printf("eax=%08x\tesp=%08x\n", reg->eax, 0); + printf("ebx=%08x\tebp=%08x\n", reg->ebx, reg->ebp); + printf("ecx=%08x\tesi=%08x\n", reg->ecx, reg->esi); + printf("edx=%08x\tedi=%08x\n", reg->edx, reg->edi); + printf("eip=%08x\n", reg->eip); +} + +void printRegs16(Reg *reg) { + printf("ax=%04x\tsp=%04x\n", LSW(reg->eax) , LSW(reg->esp)); + printf("bx=%04x\tbp=%04x\n", LSW(reg->ebx) , LSW(reg->ebp)); + printf("cx=%04x\tsi=%04x\n", LSW(reg->ecx) , LSW(reg->esi)); + printf("dx=%04x\tdi=%04x\n", LSW(reg->edx) , LSW(reg->edi)); + + printf("cs=%04x\tds=%04x\n", reg->cs , reg->ds); + printf("es=%04x\tfs=%04x\n", reg->es, reg->fs); + printf("gs=%04x\n", reg->gs); + +} /* 32bit registers */ @@ -24,9 +66,8 @@ i32 edx() { } i32 eip() { - asm("__geteip: mov eax, [esp]\n" - " ret\n" - "call __geteip"); + asm("call __next\n" + "__next: pop eax"); } i32 esp() { @@ -44,3 +85,40 @@ i32 esi() { i32 edi() { asm("mov eax, edi"); } + +/* 16bit registers */ +i16 ax() { + asm("mov bx, ax\n" + "xor eax, eax\n" + "mov ax, bx"); +} + +i16 bx() { + asm("xor eax, eax\n" + "mov ax, bx"); +} + +i16 cs() { + asm("xor eax, eax\n" + "mov ax, cs"); +} + +i16 ds() { + asm("xor eax, eax\n" + "mov ax, ds"); +} + +i16 es() { + asm("xor eax, eax\n" + "mov ax, es"); +} + +i16 fs() { + asm("xor eax, eax\n" + "mov ax, fs"); +} + +i16 gs() { + asm("xor eax, eax\n" + "mov ax, gs"); +} From ab147a5eda147be2be9c7498a91c7f35b85ef9ab Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Mon, 21 Nov 2016 04:57:28 -0200 Subject: [PATCH 4/4] VERY DIRTY HACK TO RUN ON BAREMETAL Signed-off-by: Tiago Natel de Moura --- xxx/Makefile | 48 ++- xxx/fns.h | 1 + xxx/kernel/include/xxx/stdio.h | 1 + xxx/kernel/include/xxx/term.h | 6 + xxx/kernel/include/xxx/types.h | 2 + xxx/kernel/include/xxx/vesa.h | 33 ++ xxx/kernel/stdio.c | 618 +++++++++++++++++++++++++++++++++ xxx/kernel/term.c | 49 +++ xxx/kernel/vesa.c | 22 ++ xxx/main.c | 15 + xxx/make.sh | 74 ++++ xxx/regs.c | 20 +- 12 files changed, 872 insertions(+), 17 deletions(-) create mode 100644 xxx/kernel/include/xxx/stdio.h create mode 100644 xxx/kernel/include/xxx/term.h create mode 100644 xxx/kernel/include/xxx/types.h create mode 100644 xxx/kernel/include/xxx/vesa.h create mode 100644 xxx/kernel/stdio.c create mode 100644 xxx/kernel/term.c create mode 100644 xxx/kernel/vesa.c create mode 100755 xxx/make.sh diff --git a/xxx/Makefile b/xxx/Makefile index 39ae425..3588020 100644 --- a/xxx/Makefile +++ b/xxx/Makefile @@ -1,9 +1,46 @@ -TARGET = xxx +.PHONY: build debug gdb -all: clean $(TARGET) +NASHURL = "https://github.com/NeowayLabs/nash/releases/download/v0.2.1/nash" +NASHPATH = ./scripts/.nash +NASHBIN = ./scripts/bin/nash +NASHEXEC := NASHPATH=$(NASHPATH) $(NASHBIN) -$(TARGET): - smlrcc main.c regs.c -I./include -o $(TARGET) +all: clean deps build build-baremetal + +clean: + $(NASHEXEC) ./make.sh clean + +deps: $(NASHBIN) scripts/BootProg/mkimg144 scripts/BootProg/flp144.bin + +scripts/BootProg/flp144.bin: scripts/BootProg + cd scripts/BootProg && nasm -f bin flp144.asm -o flp144.bin + +scripts/BootProg/mkimg144: scripts/BootProg + cd scripts/BootProg && smlrcc mkimg144.c -o mkimg144 + +scripts/BootProg: + mkdir -p scripts + cd scripts && git clone git@github.com:alexfru/BootProg.git + +$(NASHBIN): + mkdir -p ./scripts/bin + wget -c $(NASHURL) -O $(NASHBIN) + chmod +x $(NASHBIN) + $(NASHBIN) -version + mkdir -p $(NASHPATH)/lib + cd $(NASHPATH)/lib && git clone git@github.com:NeowayLabs/nashlib.git + +build: $(NASHBIN) + $(NASHEXEC) ./make.sh build + +baremetal: deps + $(NASHEXEC) ./make.sh baremetal + +test: + $(NASHEXEC) ./make.sh test + +gdb: + $(NASHEXEC) ./make.sh debug-gdb debug: gdb -ex "set architecture 386:386" \ @@ -12,6 +49,3 @@ debug: -ex "br *0x80490b0" \ -ex "set startup-with-shell off" \ ./xxx - -clean: - rm -f $(TARGET) diff --git a/xxx/fns.h b/xxx/fns.h index cd73f94..bd6f55d 100644 --- a/xxx/fns.h +++ b/xxx/fns.h @@ -2,3 +2,4 @@ void printRegs32(Reg*); void printRegs16(Reg*); +void init(); diff --git a/xxx/kernel/include/xxx/stdio.h b/xxx/kernel/include/xxx/stdio.h new file mode 100644 index 0000000..d9a5f1a --- /dev/null +++ b/xxx/kernel/include/xxx/stdio.h @@ -0,0 +1 @@ +uint16 printf(char *fmt, ...); diff --git a/xxx/kernel/include/xxx/term.h b/xxx/kernel/include/xxx/term.h new file mode 100644 index 0000000..1d2624e --- /dev/null +++ b/xxx/kernel/include/xxx/term.h @@ -0,0 +1,6 @@ +typedef struct { + uint8 x; + uint8 y; + + uint8 color; +} Term; diff --git a/xxx/kernel/include/xxx/types.h b/xxx/kernel/include/xxx/types.h new file mode 100644 index 0000000..b98f6c4 --- /dev/null +++ b/xxx/kernel/include/xxx/types.h @@ -0,0 +1,2 @@ +typedef unsigned char uint8; +typedef unsigned short uint16; diff --git a/xxx/kernel/include/xxx/vesa.h b/xxx/kernel/include/xxx/vesa.h new file mode 100644 index 0000000..5cd12d5 --- /dev/null +++ b/xxx/kernel/include/xxx/vesa.h @@ -0,0 +1,33 @@ +// video mode, video buffer segment and dimensions +#define VMODE 3 // 80x25 color text mode +#define VSEG 0xB800 +#define VWIDTH 80 +#define VHEIGHT 25 + +// foreground and background colors +#define FORE_BLACK 0x00 +#define FORE_BLUE 0x01 +#define FORE_GREEN 0x02 +#define FORE_CYAN 0x03 +#define FORE_RED 0x04 +#define FORE_MAGENTA 0x05 +#define FORE_BROWN 0x06 +#define FORE_WHITE 0x07 +#define FORE_GRAY 0x08 +#define FORE_BRIGHT_BLUE 0x09 +#define FORE_BRIGHT_GREEN 0x0A +#define FORE_BRIGHT_CYAN 0x0B +#define FORE_BRIGHT_RED 0x0C +#define FORE_BRIGHT_MAGENTA 0x0D +#define FORE_YELLOW 0x0E +#define FORE_BRIGHT_WHITE 0x0F +#define BACK_BLACK 0x00 +#define BACK_BLUE 0x10 +#define BACK_GREEN 0x20 +#define BACK_CYAN 0x30 +#define BACK_RED 0x40 +#define BACK_MAGENTA 0x50 +#define BACK_BROWN 0x60 +#define BACK_WHITE 0x70 + +#define TERMCOLOR (BACK_BLACK | FORE_BRIGHT_WHITE) diff --git a/xxx/kernel/stdio.c b/xxx/kernel/stdio.c new file mode 100644 index 0000000..6242244 --- /dev/null +++ b/xxx/kernel/stdio.c @@ -0,0 +1,618 @@ +/** + * Printf adapted from Alexey Frunze + * https://github.com/alexfru/SmallerC/blob/master/v0100/srclib/doprint.c + */ + +#include "xxx/types.h" +#include "xxx/term.h" + +extern Term *term; + +typedef char* va_list; +typedef int FILE; + +#define NULL (void*)0 + +#ifdef __SMALLER_C_32__ +#include + +int __cvtdif(float x, char* buf, int size, int* rem); +int __cvtdff(float x, char* buf, int size, int* zeroes); + +static +void roundupf(char* buf, int idx) +{ + do + { + if (buf[idx] == '9') + { + buf[idx] = '0'; + } + else + { + buf[idx]++; + break; + } + } while (--idx >= 0); +} + +// Define MAX_FLT_DIGS to be one greater than the maximum number of +// desired significant digits. Reducing MAX_FLT_DIGS saves stack space. +// Prints full smallest positive denormal (2**-149 ~= 1.4e-45) using "%.149f": +#define MAX_FLT_DIGS (FLT_MANT_DIG - FLT_MIN_EXP + 2) + +char * itoa(int value, char * str, int base ) +{ + char * rc; + char * ptr; + char * low; + + // Check for supported base. + if ( base < 2 || base > 36 ) + { + *str = '\0'; + return str; + } + + rc = ptr = str; + // Set '-' for negative decimals. + if ( value < 0 && base == 10 ) + { + *ptr++ = '-'; + } + // Remember where the numbers start. + low = ptr; + // The actual conversion. + do + { + // Modulo is negative for negative value. This trick makes abs() unnecessary. + *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + value % base]; + value /= base; + } while ( value ); + // Terminating the string. + *ptr-- = '\0'; + // Invert the numbers. + while ( low < ptr ) + { + char tmp = *low; + *low++ = *ptr; + *ptr-- = tmp; + } + + return rc; +} + +// Simple printf +// Only supports %s modifier until now. +uint16 printf(char *fmt, ...) { + return _doprintf(fmt, (char *)&fmt + sizeof(char *)); +} + +void __fputc(char c, int lero, int lero2[2]) { + termputchar(term, c); +} + +static +void printff(float x, int ljust, int sign, int alt, int lzeroes, + int width, int precision, int conversion, + FILE* f, int cnt[2]) +{ + char buf[1/*overflow digit when rounding*/ + MAX_FLT_DIGS]; + char ebuf[1/*e*/+1/*sign*/+2/*nn*/]; // 2 exponent digits in floats +// int neg = copysignf(1, x) < 0; // can't portably detect -0.0f otherwise +// int neg = signbit(x); // can't portably detect -0.0f otherwise + int upper = isupper(conversion); + int icnt, iz = 0, dot = 0, fcnt = 0, fz = 0, ecnt = 0, len; + char* p = buf; + union + { + float f; + unsigned u; + } u; + + conversion = tolower(conversion); + +// if (neg) x = -x, sign = '-'; + u.f = x; + if ((int)u.u < 0) + { + u.u &= 0x7FFFFFFF; + x = u.f; + sign = '-'; + } + + buf[0] = '0'; // clear rounding overflow + + if (u.u > 0x7F800000) // if (x != x) + { + lzeroes = 0; + strcpy(buf + 1, upper ? "NAN" : "nan"); + icnt = 3; + } + else if (u.u == 0x7F800000) // if (x == INFINITY) + { + lzeroes = 0; + strcpy(buf + 1, upper ? "INF" : "inf"); + icnt = 3; + } + else + { + int wasg = 0; + int gprecision; + if (conversion == 'g') + { + wasg = 1; + if (precision < 0) + precision = 6; + else if (precision == 0) + precision = 1; + // try continuing as %e + gprecision = precision--; + conversion = 'e'; + } +lf: + if (conversion == 'f') + { + int rem, lastdig; + if (precision < 0) + precision = 6; + dot = precision || alt; + icnt = __cvtdif(x, buf + 1, MAX_FLT_DIGS, &rem); + if (icnt >= MAX_FLT_DIGS) + { + // Got MAX_FLT_DIGS digits of integral part + // (and possibly some implied trailing zeroes). + // Will use the last digit for rounding. + iz = icnt - MAX_FLT_DIGS + 1; // trailing zeroes of integral part + icnt = MAX_FLT_DIGS - 1; // digits of integral part + fcnt = 0; // digits of fractional part (none) + fz = precision; // trailing zeroes of fractional part + } + else + { + // Got fewer than MAX_FLT_DIGS digits in integral part + // (and no implied trailing zeroes). + int need = precision + 1/*rounding*/; + int avail = MAX_FLT_DIGS - icnt; + iz = 0; // trailing zeroes of integral part (none) + // Get up to precision + 1 digits of fractional part. + // Will use the last digit for rounding. + fcnt = ((need < avail) ? need : avail) - 1; // digits of fractional part + fz = precision - fcnt; // trailing zeroes of fractional part + rem = __cvtdff(x, buf + 1 + icnt, fcnt + 1, NULL); + } + // Round to even + if ((lastdig = buf[1 + icnt + fcnt]) >= '5') + { + if (lastdig != '5' || rem || ((buf[icnt + fcnt] - '0') & 1)) + { + roundupf(buf, icnt + fcnt); + icnt += buf[0] != '0'; // overflow adds a digit in integral part + } + } + } + else // if (conversion == 'e') + { + int rem, lastdig; + int pow10; + int need; + int request; + if (precision < 0) + precision = 6; + dot = precision || alt; + need = precision + 2/*before dot + rounding*/; + request = (need < MAX_FLT_DIGS) ? need : MAX_FLT_DIGS; + icnt = __cvtdif(x, buf + 1, request, &rem); + if (buf[1] == '0') + { + // Integral part is zero. + // Get fractional part without leading zeroes after the decimal point + // and get the number of leading zeroes into pow10. + rem = __cvtdff(x, buf + 1, request, &pow10); + pow10 = -pow10 - (buf[1] != '0')/*0.0 should keep zero exponent*/; + } + else + { + // Integral part is non-zero. + // Get more fractional digits if needed/possible. + pow10 = icnt - 1; // convert number of integral digits to power + if (icnt >= request) + icnt = request; // correct actual number of integral digits obtained + else + rem = __cvtdff(x, buf + 1 + icnt, request - icnt, NULL); + } + icnt = 1; // digits of integral part + iz = 0; // trailing zeroes of integral part + fcnt = request - 2; // digits of fractional part + fz = precision - fcnt; // trailing zeroes of fractional part + // Round to even + if ((lastdig = buf[1 + icnt + fcnt]) >= '5') + { + if (lastdig != '5' || rem || ((buf[icnt + fcnt] - '0') & 1)) + { + roundupf(buf, icnt + fcnt); + pow10 += buf[0] != '0'; // overflow increments exponent + } + } + if (wasg) + { + // see if %f is needed instead of %e + if (pow10 >= -4 && gprecision > pow10) + { + // continue as %f + precision = gprecision - (pow10 + 1); + conversion = 'f'; + buf[0] = '0'; // clear rounding overflow + goto lf; + } + } + ebuf[0] = upper ? 'E' : 'e'; + if (pow10 < 0) + ebuf[1] = '-', pow10 = -pow10; + else + ebuf[1] = '+'; + ebuf[2] = pow10 / 10 + '0'; + ebuf[3] = pow10 % 10 + '0'; + ecnt = 4; + } + if (wasg && !alt) + { + // remove trailing fractional zeroes and dot + int i = (buf[0] == '0') + icnt + fcnt - 1; + while (fcnt && buf[i--] == '0') + fcnt--; + if (fcnt == 0) + dot = 0; + fz = 0; + } + } + + len = (sign != 0) + icnt + iz + dot + fcnt + fz + ecnt; + width = (width > len) ? (width - len) : 0; // padding + + if (!ljust && !lzeroes) + while (width) + __fputc(' ', f, cnt), width--; + + if (sign) + __fputc(sign, f, cnt); + + if (lzeroes) + while (width) + __fputc('0', f, cnt), width--; + + p += buf[0] == '0'; // skip overflow digit if no overflow + while (icnt--) + __fputc(*p++, f, cnt); + while (iz--) + __fputc('0', f, cnt); + if (dot) + __fputc('.', f, cnt); + while (fcnt--) + __fputc(*p++, f, cnt); + while (fz--) + __fputc('0', f, cnt); + + p = ebuf; + while (ecnt--) + __fputc(*p++, f, cnt); + + if (ljust) + while (width) + __fputc(' ', f, cnt), width--; +} +#endif + +int _doprintf(char* fmt, va_list vl) +{ + int f; + int cnt[2] = { 0, 0 }; // count, file write error indicator + int c; + int ljust, sign, alt, lzeroes; + int width, precision, lmodifier; + + while ((c = (unsigned char)*fmt++) != '\0') + { + if (c != '%' || *fmt == '%') + { + __fputc(c, f, cnt); + fmt += (c == '%'); + continue; + } + if ((c = (unsigned char)*fmt++) == '\0') + return -1; + + ljust = sign = alt = lzeroes = 0; + for (;;) + { + if (c == '-') + ljust = 1, lzeroes = 0; + else if (c == '+') + sign = '+'; + else if (c == ' ') + { + if (!sign) + sign = ' '; + } + else if (c == '#') + alt = 1; + else if (c == '0') + { + if (!ljust) + lzeroes = 1; + } + else + break; + + if ((c = (unsigned char)*fmt++) == '\0') + return -1; + } + + width = -1; + if (isdigit(c)) + { + width = 0; + while (isdigit(c)) + { + width = width * 10 + (c - '0'); // TBD??? overflow check??? + if ((c = (unsigned char)*fmt++) == '\0') + return -1; + } + } + else if (c == '*') + { + width = *(int*)vl; vl += sizeof(int); + if (width < 0) + { + ljust = 1; + lzeroes = 0; + width = -width; // TBD??? overflow check??? + } + if ((c = *fmt++) == '\0') + return -1; + } + + precision = -1; + if (c == '.') + { + if ((c = (unsigned char)*fmt++) == '\0') + return -1; + precision = 0; + if (isdigit(c)) + { + while (isdigit(c)) + { + precision = precision * 10 + (c - '0'); // TBD??? overflow check??? + if ((c = (unsigned char)*fmt++) == '\0') + return -1; + } + } + else if (c == '*') + { + precision = *(int*)vl; vl += sizeof(int); + if ((c = *fmt++) == '\0') + return -1; + } + } + + lmodifier = 0; + if (c == 'h') + { + if (*fmt == 'h') + { + fmt++; + lmodifier = 'H'; + } + else + { + lmodifier = c; + } + } +#ifdef __SMALLER_C_32__ + else if (c == 'l') + { + lmodifier = c; + } +#endif + else if (strchr("jzt", c)) + { + lmodifier = c; + } + if (lmodifier) + if ((c = (unsigned char)*fmt++) == '\0') + return -1; + + if (c == 'n') + { + if (lmodifier == 'H') + **(signed char**)vl = cnt[0], vl += sizeof(signed char*); + else if (lmodifier == 'h') + **(short**)vl = cnt[0], vl += sizeof(short*); + else + **(int**)vl = cnt[0], vl += sizeof(int*); + continue; + } + + if (c == 'i') + c = 'd'; +#ifdef __SMALLER_C_32__ + if (!strchr("douxXcspeEfFgG", c)) + return -1; +#else + if (!strchr("douxXcsp", c)) + return -1; +#endif + + if (c == 'c') + { + int ch = (unsigned char)*(int*)vl; + vl += sizeof(int); + + if (!ljust) + while (width > 1) + __fputc(' ', f, cnt), width--; + + __fputc(ch, f, cnt); + + if (ljust) + while (width > 1) + __fputc(' ', f, cnt), width--; + + continue; + } + else if (c == 's') + { + char* s = *(char**)vl; + int len, i; + vl += sizeof(char*); + + if (!s) + s = "(null)"; // Not defined/required by the standard, but helpful + + if (precision < 0) + { + len = strlen(s); // TBD??? overflow check??? + } + else + { + len = 0; + while (len < precision) + if (s[len]) + len++; + else + break; + } + + if (!ljust) + while (width > len) + __fputc(' ', f, cnt), width--; + + i = len; + while (i--) + __fputc(*s++, f, cnt); + + if (ljust) + while (width > len) + __fputc(' ', f, cnt), width--; + + continue; + } +#ifdef __SMALLER_C_32__ + else if (strchr("eEfFgG", c)) + { + float v = *(float*)vl; + vl += sizeof(v); + printff(v, ljust, sign, alt, lzeroes, width, precision, c, f, cnt); + continue; + } +#endif + else + { + unsigned v = *(unsigned*)vl, tmp; + char s[11]; // up to 11 octal digits in 32-bit numbers + char* p = s + sizeof s; + unsigned base = (c == 'p') ? 16 : 10; + char* digits = "0123456789abcdef"; + char* hexpfx = NULL; + int dcnt; + int len; + vl += sizeof(unsigned); + + if (precision >= 0) + lzeroes = 0; + + if (c == 'o') + base = 8; + else if (toupper(c) == 'X') + { + base = 16; + if (c == 'X') + digits = "0123456789ABCDEF"; + if (alt && v) + hexpfx = (c == 'X') ? "0X" : "0x"; + } + + if (c != 'd') + { + if (lmodifier == 'H') + v = (unsigned char)v; + else if (lmodifier == 'h') + v = (unsigned short)v; + sign = 0; + } + else + { + if (lmodifier == 'H') + v = (signed char)v; + else if (lmodifier == 'h') + v = (short)v; + if ((int)v < 0) + v = -v, sign = '-'; + } + + tmp = v; + do + { + *--p = digits[tmp % base]; + tmp /= base; + } while (tmp); + dcnt = s + sizeof s - p; + + if (precision < 0) + precision = 1; + else if (v == 0 && precision == 0) + dcnt = 0; + + if (alt && c == 'o') + if ((v == 0 && precision == 0) || (v && precision <= dcnt)) + precision = dcnt + 1; + + if (precision < dcnt) + precision = dcnt; + + // width padding: + // - left/right + // - spaces/zeroes (zeroes are to appear after sign/base prefix) + // sign: + // - '-' if negative + // - '+' or '-' always + // - space if non-negative or empty + // alt: + // - octal: prefix 0 to conversion if non-zero or empty + // - hex: prefix "0x"/"0X" to conversion if non-zero + // precision: + // - prefix conversion digits with zeroes to precision + // - special case: 0 with precision=0 results in empty conversion + + // [leading spaces] [sign/hex prefix] [leading zeroes] [(precision-dcnt) zeroes] [dcnt digits] [trailing spaces] + len = (sign != 0) + (hexpfx != NULL) * 2 + precision; + + if (!ljust && !lzeroes) + while (width > len) + __fputc(' ', f, cnt), width--; + + if (sign) + __fputc(sign, f, cnt); + else if (hexpfx) + __fputc(hexpfx[0], f, cnt), __fputc(hexpfx[1], f, cnt); + + if (!ljust && lzeroes) + while (width > len) + __fputc('0', f, cnt), width--; + + while (precision-- > dcnt) + __fputc('0', f, cnt); + + while (dcnt--) + __fputc(*p++, f, cnt); + + if (ljust) + while (width > len) + __fputc(' ', f, cnt), width--; + + continue; + } + } + + return cnt[1] ? -1 : cnt[0]; +} diff --git a/xxx/kernel/term.c b/xxx/kernel/term.c new file mode 100644 index 0000000..4da23cb --- /dev/null +++ b/xxx/kernel/term.c @@ -0,0 +1,49 @@ +#include "xxx/types.h" +#include "xxx/vesa.h" +#include "xxx/term.h" + +void terminit(Term *term) { + term->x = 0; + term->y = 0; + term->color = TERMCOLOR; +} + +void termputchar(Term *term, char c) { + if (c == '\r') { + term->x = 0; + return; + } + + if (c == '\n') { + uint8 erasecolumns = (VWIDTH-1) - term->x; + + for (uint8 i = 0; i < erasecolumns; i++) { + termputchar(term, ' '); + } + + term->y++; + term->x = 0; + + return; + } + + putchar(term->x, term->y, c, term->color); + term->x++; + + if (term->x == VWIDTH) { + term->x = 0; + term->y++; + } + + if (term->y == VHEIGHT) { + term->x = 0; + term->y = 0; + } +} + +void termputstr(Term *term, char *str) { + char c; + while ((c = *str++) != '\0') { + termputchar(term, c); + } +} diff --git a/xxx/kernel/vesa.c b/xxx/kernel/vesa.c new file mode 100644 index 0000000..4862736 --- /dev/null +++ b/xxx/kernel/vesa.c @@ -0,0 +1,22 @@ +#include "xxx/types.h" + +void putchar(uint8 x, uint8 y, char c, uint16 color) { + volatile uint16 * where; + where = (volatile uint16 *)0xB8000 + (y * 80 + x) ; + *where = c | (color << 8); +} + +uint16 putn(uint8 x, uint8 y, char *s, uint16 sz, unsigned color) { + uint16 i = 0; + + for (i = 0; i < sz; i++) { + putchar(x+i, y, s[i], color); + } + + return i; +} + +uint16 putstr(uint8 x, uint8 y, char *s, uint8 color) +{ + return putn(x, y, s, strlen(s), color); +} diff --git a/xxx/main.c b/xxx/main.c index f16a9f9..8ecbd87 100644 --- a/xxx/main.c +++ b/xxx/main.c @@ -1,8 +1,23 @@ #include + +/* xxx kernel headers */ +#include "xxx/types.h" +#include "xxx/vesa.h" +#include "xxx/term.h" + +/* xxx headers */ #include "dat.h" #include "fns.h" +Term *term; + int main() { + Term t; + + term = &t; + + terminit(term); + Reg reg; newreg(®); diff --git a/xxx/make.sh b/xxx/make.sh new file mode 100755 index 0000000..19fea07 --- /dev/null +++ b/xxx/make.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env nash + +import nashlib/sed + +Target = "xxx" +Sources = (main.c regs.c) +KSources = ( + kernel/init.c + kernel/term.c + kernel/vesa.c + kernel/stdio.c +) + +KernelImg = "flp144.img" + +setenv PATH = $PATH+":"+"./scripts/BootProg" + +fn help() { + printf "Use %s \n" $ARGS[0] + printf "Actions:\n" + printf "\tbuild\t\t Build the userspace debugger\n" + printf "\tbuild-metal\tBuild the bare metal version\n" + printf "\tclean\t Clean the repo\n" +} + +fn build() { + smlrcc $Sources -I./include -o $Target + echo "Built successfully" +} + +fn buildImage() { + mkimg144 -bs ./scripts/BootProg/flp144.bin -o $KernelImg -us STARTUP.BIN +} + +fn buildMetal() { + smlrcc -dosu $Sources $KSources -I ./kernel/include -o STARTUP.BIN +} + +fn baremetal() { + buildMetal() + buildImage() + + qemu-system-i386 -fda $KernelImg -m 128 +} + +fn clean() { + rm -f $Target +} + +fn main() { + arglen <= len($ARGS) + + action = $ARGS[1] + + -expr $arglen "<" 2 >[1=] + + if $status == "0" { + # too few arguments + help() + + return + } + if $action == "clean" { + clean() + } else if $action == "build" { + build() + } else if $action == "baremetal" { + baremetal() + } else { + printf "Unexpected command '%s'.\n" $action + } +} + +main() diff --git a/xxx/regs.c b/xxx/regs.c index f316cc2..c200d86 100644 --- a/xxx/regs.c +++ b/xxx/regs.c @@ -28,21 +28,21 @@ void newreg(Reg *reg) { } void printRegs32(Reg *reg) { - printf("eax=%08x\tesp=%08x\n", reg->eax, 0); - printf("ebx=%08x\tebp=%08x\n", reg->ebx, reg->ebp); - printf("ecx=%08x\tesi=%08x\n", reg->ecx, reg->esi); - printf("edx=%08x\tedi=%08x\n", reg->edx, reg->edi); + printf("eax=%08x esp=%08x\n", reg->eax, 0); + printf("ebx=%08x ebp=%08x\n", reg->ebx, reg->ebp); + printf("ecx=%08x esi=%08x\n", reg->ecx, reg->esi); + printf("edx=%08x edi=%08x\n", reg->edx, reg->edi); printf("eip=%08x\n", reg->eip); } void printRegs16(Reg *reg) { - printf("ax=%04x\tsp=%04x\n", LSW(reg->eax) , LSW(reg->esp)); - printf("bx=%04x\tbp=%04x\n", LSW(reg->ebx) , LSW(reg->ebp)); - printf("cx=%04x\tsi=%04x\n", LSW(reg->ecx) , LSW(reg->esi)); - printf("dx=%04x\tdi=%04x\n", LSW(reg->edx) , LSW(reg->edi)); + printf("ax=%04x sp=%04x\n", LSW(reg->eax) , LSW(reg->esp)); + printf("bx=%04x bp=%04x\n", LSW(reg->ebx) , LSW(reg->ebp)); + printf("cx=%04x si=%04x\n", LSW(reg->ecx) , LSW(reg->esi)); + printf("dx=%04x di=%04x\n", LSW(reg->edx) , LSW(reg->edi)); - printf("cs=%04x\tds=%04x\n", reg->cs , reg->ds); - printf("es=%04x\tfs=%04x\n", reg->es, reg->fs); + printf("cs=%04x ds=%04x\n", reg->cs , reg->ds); + printf("es=%04x fs=%04x\n", reg->es, reg->fs); printf("gs=%04x\n", reg->gs); }