From aee4ce37ee5240552b71b9e2b893e135f6a58bd5 Mon Sep 17 00:00:00 2001 From: VinceAle7082 Date: Sat, 7 Sep 2024 19:47:25 +0200 Subject: [PATCH] Implemented printf! --- src/bootloader/stage2/Makefile | 5 +- src/bootloader/stage2/linker.lnk | 12 +- src/bootloader/stage2/main.asm | 22 +++ src/bootloader/stage2/main.c | 9 +- src/bootloader/stage2/stdint.h | 9 +- src/bootloader/stage2/stdio.c | 305 +++++++++++++++---------------- src/bootloader/stage2/stdio.h | 3 +- src/bootloader/stage2/x86.asm | 25 ++- src/bootloader/stage2/x86.h | 3 +- 9 files changed, 215 insertions(+), 178 deletions(-) create mode 100644 src/bootloader/stage2/main.asm diff --git a/src/bootloader/stage2/Makefile b/src/bootloader/stage2/Makefile index da46177..1c25129 100644 --- a/src/bootloader/stage2/Makefile +++ b/src/bootloader/stage2/Makefile @@ -1,9 +1,8 @@ BUILD_DIR?=build/ ASM?=nasm ASMFLAGS?=-f obj -CC?=gcc CC16?=/usr/bin/watcom/binl/wcc -CFLAGS16?= -4 -d3 -s -wx -ms -zl -zq +CFLAGS16?=-4 -d3 -s -wx -ms -zl -zq # -oneatxzh LD16?=/usr/bin/watcom/binl/wlink SOURCES_C=$(wildcard *.c) @@ -11,7 +10,7 @@ SOURCES_ASM=$(wildcard *.asm) OBJECTS_C=$(patsubst %.c, $(BUILD_DIR)/stage2/c/%.obj, $(SOURCES_C)) OBJECTS_ASM=$(patsubst %.asm, $(BUILD_DIR)/stage2/asm/%.obj, $(SOURCES_ASM)) -.PHONY: all clean always +.PHONY: all stage2 clean always all: stage2 diff --git a/src/bootloader/stage2/linker.lnk b/src/bootloader/stage2/linker.lnk index 2942bbb..612fed6 100644 --- a/src/bootloader/stage2/linker.lnk +++ b/src/bootloader/stage2/linker.lnk @@ -1,12 +1,12 @@ FORMAT RAW BIN OPTION QUIET, - NODEFAULTLIBS, - START=entry, - VERBOSE, - OFFSET=0, - STACK=0X200 + NODEFAULTLIBS, + START=entry, + VERBOSE, + OFFSET=0, + STACK=0x200 ORDER CLNAME CODE SEGMENT _ENTRY SEGMENT _TEXT - CLNAME DATA + CLNAME DATA \ No newline at end of file diff --git a/src/bootloader/stage2/main.asm b/src/bootloader/stage2/main.asm new file mode 100644 index 0000000..694c448 --- /dev/null +++ b/src/bootloader/stage2/main.asm @@ -0,0 +1,22 @@ +bits 16 + +section _ENTRY class=CODE + +extern _cstart_ +global entry + +entry: + cli + + mov ax, ds + mov ss, ax + mov sp, 0 + mov bp, sp + sti + + xor dh, dh + push dx + call _cstart_ + + cli + hlt diff --git a/src/bootloader/stage2/main.c b/src/bootloader/stage2/main.c index 1e7137d..49fcd6f 100644 --- a/src/bootloader/stage2/main.c +++ b/src/bootloader/stage2/main.c @@ -3,6 +3,11 @@ void _cdecl cstart_(uint16_t bootDrive) { - puts("Hello World from the Stage 2 of the bootloader written in C!"); + const char far* far_str = "far string"; + + puts("Hello world from stage 2 of the bootloader written in C!\r\n"); + printf("Formatted %% %c %s %ls\r\n", 'a', "string", far_str); + printf("Formatted %d %i %x %p %o %hd %hi %hhu %hhd\r\n", 1234, -5678, 0xdead, 0xbeef, 012345, (short)27, (short)-42, (unsigned char)20, (signed char)-10); + printf("Formatted %ld %lx %lld %llx\r\n", -100000000l, 0xdeadbeeful, 10200300400ll, 0xdeadbeeffeebdaedull); for (;;); -} \ No newline at end of file +} diff --git a/src/bootloader/stage2/stdint.h b/src/bootloader/stage2/stdint.h index 2999fd9..9ea757e 100644 --- a/src/bootloader/stage2/stdint.h +++ b/src/bootloader/stage2/stdint.h @@ -6,9 +6,12 @@ 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 int int64_t; -typedef unsigned long int uint64_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 +#define true 1 + + diff --git a/src/bootloader/stage2/stdio.c b/src/bootloader/stage2/stdio.c index c9aa479..9cc6d21 100644 --- a/src/bootloader/stage2/stdio.c +++ b/src/bootloader/stage2/stdio.c @@ -5,7 +5,17 @@ void putc(char c) { x86_Video_WriteCharTeletype(c, 0); } -void puts(const char *str) + +void puts(const char* str) +{ + while(*str) + { + putc(*str); + str++; + } +} + +void puts_f(const char far* str) { while(*str) { @@ -26,11 +36,11 @@ void puts(const char *str) #define PRINTF_LENGTH_LONG 3 #define PRINTF_LENGTH_LONG_LONG 4 -int * printf_number(int *argp, int length, bool sign, int radix); +int* printf_number(int* argp, int length, bool sign, int radix); -void _cdecl printf(const char *fmt, ...) +void _cdecl printf(const char* fmt, ...) { - int *argp = (int *)&fmt; + int* argp = (int*)&fmt; int state = PRINTF_STATE_NORMAL; int length = PRINTF_LENGTH_DEFAULT; int radix = 10; @@ -42,118 +52,97 @@ void _cdecl printf(const char *fmt, ...) { switch (state) { - case PRINTF_STATE_NORMAL: - switch (*fmt) - { - case '%': - state = PRINTF_STATE_LENGTH; - break; - default: - putc(*fmt); - break; - } - break; - - case PRINTF_STATE_LENGTH: - switch (*fmt) - { - case 'h': - length = PRINTF_LENGTH_SHORT; - state = PRINTF_STATE_LENGTH_SHORT; - break; - case 'l': - length = PRINTF_LENGTH_LONG; - state = PRINTF_STATE_LENGTH_LONG; - break; - default: - goto PRINTF_STATE_SPEC_; - } - break; - - case PRINTF_STATE_LENGTH_SHORT: - if (*fmt == 'h') - { - length = PRINTF_LENGTH_SHORT_SHORT; - state = PRINTF_STATE_SPEC; - } - else - goto PRINTF_STATE_SPEC_; - break; - - case PRINTF_STATE_LENGTH_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': - if (length == PRINTF_LENGTH_LONG || length == PRINTF_LENGTH_LONG_LONG) + case PRINTF_STATE_NORMAL: + switch (*fmt) { - puts_f(*(const char far **)argp); - argp += 2; - } - else - { - puts(*(const char **)argp); - argp++; + case '%': state = PRINTF_STATE_LENGTH; + break; + default: putc(*fmt); + break; } break; - case '%': - putc('%'); + case PRINTF_STATE_LENGTH: + switch (*fmt) + { + case 'h': length = PRINTF_LENGTH_SHORT; + state = PRINTF_STATE_LENGTH_SHORT; + break; + case 'l': length = PRINTF_LENGTH_LONG; + state = PRINTF_STATE_LENGTH_LONG; + break; + default: goto PRINTF_STATE_SPEC_; + } break; - case 'd': - case 'i': - radix = 10; - sign = true; - argp = printf_number(argp, length, sign, radix); + case PRINTF_STATE_LENGTH_SHORT: + if (*fmt == 'h') + { + length = PRINTF_LENGTH_SHORT_SHORT; + state = PRINTF_STATE_SPEC; + } + else goto PRINTF_STATE_SPEC_; break; - case 'u': + case PRINTF_STATE_LENGTH_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': if (length == PRINTF_LENGTH_LONG || length == PRINTF_LENGTH_LONG_LONG) + { + puts_f(*(const char far**)argp); + argp += 2; + } + else + { + 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_NORMAL; + length = PRINTF_LENGTH_DEFAULT; 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; - - // ignore invalid spec - default: - break; - } - - // reset state - state = PRINTF_STATE_NORMAL; - length = PRINTF_LENGTH_DEFAULT; - radix = 10; - sign = false; - break; } fmt++; @@ -162,88 +151,84 @@ void _cdecl printf(const char *fmt, ...) const char g_HexChars[] = "0123456789abcdef"; -int *printf_number(int *argp, int length, bool sign, int radix) +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; - // process length switch (length) { - case PRINTF_LENGTH_SHORT_SHORT: - case PRINTF_LENGTH_SHORT: - case PRINTF_LENGTH_DEFAULT: - if (sign) - { - int n = *argp; - if (n < 0) + case PRINTF_LENGTH_SHORT_SHORT: + case PRINTF_LENGTH_SHORT: + case PRINTF_LENGTH_DEFAULT: + if (sign) { - n = -n; - number_sign = -1; + int n = *argp; + if (n < 0) + { + n = -n; + number_sign = -1; + } + number = (unsigned long long)n; } - number = (unsigned long long)n; - } - else - { - number = *(unsigned int *)argp; - } - argp++; - break; + else + { + number = *(unsigned int*)argp; + } + argp++; + break; - case PRINTF_LENGTH_LONG: - if (sign) - { - long int n = *(long int *)argp; - if (n < 0) + case PRINTF_LENGTH_LONG: + if (sign) { - n = -n; - number_sign = -1; + long int n = *(long int*)argp; + if (n < 0) + { + n = -n; + number_sign = -1; + } + number = (unsigned long long)n; } - number = (unsigned long long)n; - } - else - { - number = *(unsigned long int *)argp; - } - argp += 2; - break; + 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) + case PRINTF_LENGTH_LONG_LONG: + if (sign) { - n = -n; - number_sign = -1; + long long int n = *(long long int*)argp; + if (n < 0) + { + n = -n; + number_sign = -1; + } + number = (unsigned long long)n; } - number = (unsigned long long)n; - } - else - { - number = *(unsigned long long int *)argp; - } - argp += 4; - break; + else + { + number = *(unsigned long long int*)argp; + } + argp += 4; + break; } - // convert number to ASCII do { - uint32_t rem = number % radix; - number = number / radix; + uint32_t rem; + x86_div64_32(number, radix, &number, &rem); buffer[pos++] = g_HexChars[rem]; } while (number > 0); - // add sign if (sign && number_sign < 0) buffer[pos++] = '-'; - // print number in reverse order while (--pos >= 0) putc(buffer[pos]); return argp; -} \ No newline at end of file +} diff --git a/src/bootloader/stage2/stdio.h b/src/bootloader/stage2/stdio.h index 0735127..b76e0dc 100644 --- a/src/bootloader/stage2/stdio.h +++ b/src/bootloader/stage2/stdio.h @@ -2,4 +2,5 @@ void putc(char c); void puts(const char* str); -void _cdecl printf(const char *fmt, ...); \ No newline at end of file +void puts_f(const char far* str); +void _cdecl printf(const char* fmt, ...); diff --git a/src/bootloader/stage2/x86.asm b/src/bootloader/stage2/x86.asm index 706f4fe..3bab9da 100644 --- a/src/bootloader/stage2/x86.asm +++ b/src/bootloader/stage2/x86.asm @@ -16,7 +16,7 @@ _x86_Video_WriteCharTeletype: int 10h pop bx - + mov sp, bp pop bp @@ -24,4 +24,25 @@ _x86_Video_WriteCharTeletype: global _x86_div64_32 -_x86_div64_32: \ No newline at end of file +_x86_div64_32: + push bp + mov bp, sp + + push bx + mov eax, [bp + 4] + 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 + pop bx + + mov sp, bp + pop bp + + ret diff --git a/src/bootloader/stage2/x86.h b/src/bootloader/stage2/x86.h index 8a057dc..06622db 100644 --- a/src/bootloader/stage2/x86.h +++ b/src/bootloader/stage2/x86.h @@ -1,5 +1,6 @@ #pragma once #include "stdint.h" +void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut); + void _cdecl x86_Video_WriteCharTeletype(char c, uint8_t page); -void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t *quotientOut, uint64_t *remainderOut); \ No newline at end of file