diff --git a/io.h b/io.h index 17894e6..24fba56 100644 --- a/io.h +++ b/io.h @@ -1,7 +1,10 @@ #ifndef INCLUDE_IO_H #define INCLUDE_IO_H +#include "stdint.h" + void outb(unsigned short port, unsigned char data); unsigned char inb(unsigned short port); +void x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut); #endif diff --git a/io.s b/io.s index 1cac568..bb131d9 100644 --- a/io.s +++ b/io.s @@ -12,3 +12,23 @@ inb: mov dx, [esp + 4] in al, dx ret + +global x86_div64_32 + +x86_div64_32: + mov eax, [bp+8] + mov ecx, [bp+12] + xor edx, edx + div ecx + + mov bx, [bp+16] + mov [bx+4], eax + + mov eax, [bp+4] + div ecx + + mov [bx], eax + mov bx, [bp+18] + mov [bx], edx + + ret diff --git a/iso/boot/kernel.elf b/iso/boot/kernel.elf index dda24bd..a133913 100755 Binary files a/iso/boot/kernel.elf and b/iso/boot/kernel.elf differ diff --git a/kernel.elf b/kernel.elf index dda24bd..a133913 100755 Binary files a/kernel.elf and b/kernel.elf differ diff --git a/kmain.c b/kmain.c index d5803bf..9e75d2b 100644 --- a/kmain.c +++ b/kmain.c @@ -8,7 +8,6 @@ int kmain(int retvalue) log("Kernel started", 2); clear(); - puts("hello\nbrave\nnew\nworld"); - + printf("Formatted: %% %c %s %d\n", 'f', "Hello", 77); return retvalue; } diff --git a/os.iso b/os.iso index 9e62f36..3af65ac 100644 Binary files a/os.iso and b/os.iso differ diff --git a/stdint.h b/stdint.h new file mode 100644 index 0000000..1da6019 --- /dev/null +++ b/stdint.h @@ -0,0 +1,20 @@ +#ifndef INCLUDE_STDINT_H +#define INCLUDE_STDINT_H + +typedef signed char int8_t; +typedef unsigned char uint8_t; + +typedef signed short int16_t; +typedef unsigned short uint16_t; + +typedef signed long int int32_t; +typedef unsigned long int uint32_t; + +typedef signed long long int int64_t; +typedef unsigned long long int uint64_t; + +typedef uint8_t bool; +#define true 1 +#define false 0 + +#endif diff --git a/stdio.c b/stdio.c index 7c67037..27e43d0 100644 --- a/stdio.c +++ b/stdio.c @@ -1,6 +1,7 @@ #include "io.h" #include "stdio.h" #include "string.h" +#include "stdint.h" char* fb = (char *) 0x000B8000; const unsigned VGA_WIDTH = 80; @@ -110,3 +111,191 @@ void puts(const char* str) } } +void printf(const char* fmt, ...) +{ + int* argp = (int*) &fmt; + int state = PRINTF_STATE_START; + int length = PRINTF_LENGTH_START; + int radix = 10; + bool sign = false; + + argp++; + while (*fmt) + { + switch(state) { + case PRINTF_STATE_START: + if (*fmt == '%') + { + state = PRINTF_STATE_LENGTH; + } + else { + putc(*fmt); + } + break; + case PRINTF_STATE_LENGTH: + if (*fmt == 'h') + { + length = PRINTF_LENGTH_SHORT; + state = PRINTF_STATE_SHORT; + } + else if (*fmt == 'l') + { + length = PRINTF_LENGTH_LONG; + state = PRINTF_STATE_LONG; + } + else { + goto PRINTF_STATE_SPEC_; + } + break; + case PRINTF_STATE_SHORT: + if (*fmt == 'h') + { + length = PRINTF_LENGTH_SHORT_SHORT; + state = PRINTF_STATE_SPEC; + } + else { + goto PRINTF_STATE_SPEC_; + } + break; + case PRINTF_STATE_LONG: + if (*fmt == 'l') + { + length = PRINTF_LENGTH_LONG_LONG; + state = PRINTF_STATE_SPEC; + } + else { + goto PRINTF_STATE_SPEC_; + } + break; + case PRINTF_STATE_SPEC: + PRINTF_STATE_SPEC_: + switch(*fmt) + { + case 'c': + putc((char)*argp); + argp++; + break; + case 's': + puts(*(const char **)argp); + argp++; + break; + case '%': + putc('%'); + break; + case 'd': + case 'i': + radix = 10; + sign = true; + argp = printf_number(argp, length, sign, radix); + break; + case 'u': + radix = 10; + sign = false; + argp = printf_number(argp, length, sign, radix); + break; + case 'X': + case 'x': + case 'p': + radix = 16; + sign = false; + argp = printf_number(argp, length, sign, radix); + break; + case 'o': + radix = 8; + sign = false; + argp = printf_number(argp, length, sign, radix); + break; + default: + break; + } + state = PRINTF_STATE_START; + length = PRINTF_LENGTH_START; + radix = 10; + sign = false; + break; + } + fmt++; + } +} + +const char charset[] = "0123456789abcdef"; + +int* printf_number(int* argp, int length, bool sign, int radix) +{ + char buffer[32]; + unsigned long long number; + int number_sign = 1; + int pos = 0; + + switch(length) + { + case PRINTF_LENGTH_SHORT_SHORT: + case PRINTF_LENGTH_SHORT: + case PRINTF_LENGTH_START: + if (sign) + { + int n = *argp; + if (n < 0) + { + n = -n; + number_sign = -1; + } + number = (unsigned long long) n; + } + else { + number = *(unsigned int*) argp; + } + argp++; + break; + case PRINTF_LENGTH_LONG: + if (sign) + { + long int n = *(long int*)argp; + if (n < 0) + { + n = -n; + number_sign = -1; + } + number = (unsigned long long) n; + } + else { + number = *(unsigned long int*) argp; + } + argp += 2; + break; + case PRINTF_LENGTH_LONG_LONG: + if (sign) + { + long long int n = *(long long int*)argp; + if (n < 0) + { + n = -n; + number_sign = -1; + } + number = (unsigned long long) n; + } + else { + number = *(unsigned long long int*) argp; + } + argp += 4; + break; + } + + do { + uint32_t rem; + x86_div64_32(number, radix, &number, &rem); + buffer[pos++] = charset[rem]; + } while (number > 0); + + if (sign && number_sign < 0) + { + buffer[pos++] = '-'; + } + + while (--pos >= 0) + { + putc(buffer[pos]); + } + + return argp; +} diff --git a/stdio.h b/stdio.h index a3a427f..f1c2106 100644 --- a/stdio.h +++ b/stdio.h @@ -1,6 +1,8 @@ #ifndef INCLUDE_STDIO_H #define INCLUDE_STDIO_H +#include "stdint.h" + #define FB_GREEN 2 #define FB_DARK_GREY 8 @@ -19,4 +21,19 @@ unsigned int getcolor(int x, int y); void scroll(int lines); void putc(char c); +#define PRINTF_STATE_START 0 +#define PRINTF_STATE_LENGTH 1 +#define PRINTF_STATE_SHORT 2 +#define PRINTF_STATE_LONG 3 +#define PRINTF_STATE_SPEC 4 + +#define PRINTF_LENGTH_START 0 +#define PRINTF_LENGTH_SHORT_SHORT 1 +#define PRINTF_LENGTH_SHORT 2 +#define PRINTF_LENGTH_LONG 3 +#define PRINTF_LENGTH_LONG_LONG 4 + +void printf(const char* fmt, ...); +int* printf_number(int* argp, int length, bool sign, int radix); + #endif