Implemented printf!

This commit is contained in:
Vincenzo Aleksey Brocato 2024-09-07 19:47:25 +02:00 committed by VinceAle7082
parent 2357008a54
commit 13297c2d9a
9 changed files with 215 additions and 178 deletions

View File

@ -1,9 +1,8 @@
BUILD_DIR?=build/ BUILD_DIR?=build/
ASM?=nasm ASM?=nasm
ASMFLAGS?=-f obj ASMFLAGS?=-f obj
CC?=gcc
CC16?=/usr/bin/watcom/binl/wcc 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 LD16?=/usr/bin/watcom/binl/wlink
SOURCES_C=$(wildcard *.c) SOURCES_C=$(wildcard *.c)
@ -11,7 +10,7 @@ SOURCES_ASM=$(wildcard *.asm)
OBJECTS_C=$(patsubst %.c, $(BUILD_DIR)/stage2/c/%.obj, $(SOURCES_C)) OBJECTS_C=$(patsubst %.c, $(BUILD_DIR)/stage2/c/%.obj, $(SOURCES_C))
OBJECTS_ASM=$(patsubst %.asm, $(BUILD_DIR)/stage2/asm/%.obj, $(SOURCES_ASM)) OBJECTS_ASM=$(patsubst %.asm, $(BUILD_DIR)/stage2/asm/%.obj, $(SOURCES_ASM))
.PHONY: all clean always .PHONY: all stage2 clean always
all: stage2 all: stage2

View File

@ -4,7 +4,7 @@ OPTION QUIET,
START=entry, START=entry,
VERBOSE, VERBOSE,
OFFSET=0, OFFSET=0,
STACK=0X200 STACK=0x200
ORDER ORDER
CLNAME CODE CLNAME CODE
SEGMENT _ENTRY SEGMENT _ENTRY

View File

@ -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

View File

@ -3,6 +3,11 @@
void _cdecl cstart_(uint16_t bootDrive) 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 (;;); for (;;);
} }

View File

@ -6,9 +6,12 @@ typedef signed short int16_t;
typedef unsigned short uint16_t; typedef unsigned short uint16_t;
typedef signed long int int32_t; typedef signed long int int32_t;
typedef unsigned long int uint32_t; typedef unsigned long int uint32_t;
typedef signed long int int64_t; typedef signed long long int int64_t;
typedef unsigned long int uint64_t; typedef unsigned long long int uint64_t;
typedef uint8_t bool; typedef uint8_t bool;
#define true 1
#define false 0 #define false 0
#define true 1

View File

@ -5,7 +5,17 @@ void putc(char c)
{ {
x86_Video_WriteCharTeletype(c, 0); 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) while(*str)
{ {
@ -26,11 +36,11 @@ void puts(const char *str)
#define PRINTF_LENGTH_LONG 3 #define PRINTF_LENGTH_LONG 3
#define PRINTF_LENGTH_LONG_LONG 4 #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 state = PRINTF_STATE_NORMAL;
int length = PRINTF_LENGTH_DEFAULT; int length = PRINTF_LENGTH_DEFAULT;
int radix = 10; int radix = 10;
@ -45,11 +55,9 @@ void _cdecl printf(const char *fmt, ...)
case PRINTF_STATE_NORMAL: case PRINTF_STATE_NORMAL:
switch (*fmt) switch (*fmt)
{ {
case '%': case '%': state = PRINTF_STATE_LENGTH;
state = PRINTF_STATE_LENGTH;
break; break;
default: default: putc(*fmt);
putc(*fmt);
break; break;
} }
break; break;
@ -57,16 +65,13 @@ void _cdecl printf(const char *fmt, ...)
case PRINTF_STATE_LENGTH: case PRINTF_STATE_LENGTH:
switch (*fmt) switch (*fmt)
{ {
case 'h': case 'h': length = PRINTF_LENGTH_SHORT;
length = PRINTF_LENGTH_SHORT;
state = PRINTF_STATE_LENGTH_SHORT; state = PRINTF_STATE_LENGTH_SHORT;
break; break;
case 'l': case 'l': length = PRINTF_LENGTH_LONG;
length = PRINTF_LENGTH_LONG;
state = PRINTF_STATE_LENGTH_LONG; state = PRINTF_STATE_LENGTH_LONG;
break; break;
default: default: goto PRINTF_STATE_SPEC_;
goto PRINTF_STATE_SPEC_;
} }
break; break;
@ -76,8 +81,7 @@ void _cdecl printf(const char *fmt, ...)
length = PRINTF_LENGTH_SHORT_SHORT; length = PRINTF_LENGTH_SHORT_SHORT;
state = PRINTF_STATE_SPEC; state = PRINTF_STATE_SPEC;
} }
else else goto PRINTF_STATE_SPEC_;
goto PRINTF_STATE_SPEC_;
break; break;
case PRINTF_STATE_LENGTH_LONG: case PRINTF_STATE_LENGTH_LONG:
@ -86,69 +90,54 @@ void _cdecl printf(const char *fmt, ...)
length = PRINTF_LENGTH_LONG_LONG; length = PRINTF_LENGTH_LONG_LONG;
state = PRINTF_STATE_SPEC; state = PRINTF_STATE_SPEC;
} }
else else goto PRINTF_STATE_SPEC_;
goto PRINTF_STATE_SPEC_;
break; break;
case PRINTF_STATE_SPEC: case PRINTF_STATE_SPEC:
PRINTF_STATE_SPEC_: PRINTF_STATE_SPEC_:
switch (*fmt) switch (*fmt)
{ {
case 'c': case 'c': putc((char)*argp);
putc((char)*argp);
argp++; argp++;
break; break;
case 's': case 's': if (length == PRINTF_LENGTH_LONG || length == PRINTF_LENGTH_LONG_LONG)
if (length == PRINTF_LENGTH_LONG || length == PRINTF_LENGTH_LONG_LONG)
{ {
puts_f(*(const char far **)argp); puts_f(*(const char far**)argp);
argp += 2; argp += 2;
} }
else else
{ {
puts(*(const char **)argp); puts(*(const char**)argp);
argp++; argp++;
} }
break; break;
case '%': case '%': putc('%');
putc('%');
break; break;
case 'd': case 'd':
case 'i': case 'i': radix = 10; sign = true;
radix = 10;
sign = true;
argp = printf_number(argp, length, sign, radix); argp = printf_number(argp, length, sign, radix);
break; break;
case 'u': case 'u': radix = 10; sign = false;
radix = 10;
sign = false;
argp = printf_number(argp, length, sign, radix); argp = printf_number(argp, length, sign, radix);
break; break;
case 'X': case 'X':
case 'x': case 'x':
case 'p': case 'p': radix = 16; sign = false;
radix = 16;
sign = false;
argp = printf_number(argp, length, sign, radix); argp = printf_number(argp, length, sign, radix);
break; break;
case 'o': case 'o': radix = 8; sign = false;
radix = 8;
sign = false;
argp = printf_number(argp, length, sign, radix); argp = printf_number(argp, length, sign, radix);
break; break;
// ignore invalid spec default: break;
default:
break;
} }
// reset state
state = PRINTF_STATE_NORMAL; state = PRINTF_STATE_NORMAL;
length = PRINTF_LENGTH_DEFAULT; length = PRINTF_LENGTH_DEFAULT;
radix = 10; radix = 10;
@ -162,14 +151,13 @@ void _cdecl printf(const char *fmt, ...)
const char g_HexChars[] = "0123456789abcdef"; 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]; char buffer[32];
unsigned long long number; unsigned long long number;
int number_sign = 1; int number_sign = 1;
int pos = 0; int pos = 0;
// process length
switch (length) switch (length)
{ {
case PRINTF_LENGTH_SHORT_SHORT: case PRINTF_LENGTH_SHORT_SHORT:
@ -187,7 +175,7 @@ int *printf_number(int *argp, int length, bool sign, int radix)
} }
else else
{ {
number = *(unsigned int *)argp; number = *(unsigned int*)argp;
} }
argp++; argp++;
break; break;
@ -195,7 +183,7 @@ int *printf_number(int *argp, int length, bool sign, int radix)
case PRINTF_LENGTH_LONG: case PRINTF_LENGTH_LONG:
if (sign) if (sign)
{ {
long int n = *(long int *)argp; long int n = *(long int*)argp;
if (n < 0) if (n < 0)
{ {
n = -n; n = -n;
@ -205,7 +193,7 @@ int *printf_number(int *argp, int length, bool sign, int radix)
} }
else else
{ {
number = *(unsigned long int *)argp; number = *(unsigned long int*)argp;
} }
argp += 2; argp += 2;
break; break;
@ -213,7 +201,7 @@ int *printf_number(int *argp, int length, bool sign, int radix)
case PRINTF_LENGTH_LONG_LONG: case PRINTF_LENGTH_LONG_LONG:
if (sign) if (sign)
{ {
long long int n = *(long long int *)argp; long long int n = *(long long int*)argp;
if (n < 0) if (n < 0)
{ {
n = -n; n = -n;
@ -223,25 +211,22 @@ int *printf_number(int *argp, int length, bool sign, int radix)
} }
else else
{ {
number = *(unsigned long long int *)argp; number = *(unsigned long long int*)argp;
} }
argp += 4; argp += 4;
break; break;
} }
// convert number to ASCII
do do
{ {
uint32_t rem = number % radix; uint32_t rem;
number = number / radix; x86_div64_32(number, radix, &number, &rem);
buffer[pos++] = g_HexChars[rem]; buffer[pos++] = g_HexChars[rem];
} while (number > 0); } while (number > 0);
// add sign
if (sign && number_sign < 0) if (sign && number_sign < 0)
buffer[pos++] = '-'; buffer[pos++] = '-';
// print number in reverse order
while (--pos >= 0) while (--pos >= 0)
putc(buffer[pos]); putc(buffer[pos]);

View File

@ -2,4 +2,5 @@
void putc(char c); void putc(char c);
void puts(const char* str); void puts(const char* str);
void _cdecl printf(const char *fmt, ...); void puts_f(const char far* str);
void _cdecl printf(const char* fmt, ...);

View File

@ -25,3 +25,24 @@ _x86_Video_WriteCharTeletype:
global _x86_div64_32 global _x86_div64_32
_x86_div64_32: _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

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "stdint.h" #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_Video_WriteCharTeletype(char c, uint8_t page);
void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t *quotientOut, uint64_t *remainderOut);