Implemented printf!
This commit is contained in:
parent
0f74ff0432
commit
aee4ce37ee
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
22
src/bootloader/stage2/main.asm
Normal file
22
src/bootloader/stage2/main.asm
Normal 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
|
@ -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 (;;);
|
||||||
}
|
}
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ 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)
|
while(*str)
|
||||||
@ -14,6 +15,15 @@ void puts(const char *str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void puts_f(const char far* str)
|
||||||
|
{
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
putc(*str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define PRINTF_STATE_NORMAL 0
|
#define PRINTF_STATE_NORMAL 0
|
||||||
#define PRINTF_STATE_LENGTH 1
|
#define PRINTF_STATE_LENGTH 1
|
||||||
#define PRINTF_STATE_LENGTH_SHORT 2
|
#define PRINTF_STATE_LENGTH_SHORT 2
|
||||||
@ -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,21 +90,18 @@ 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;
|
||||||
@ -112,43 +113,31 @@ void _cdecl printf(const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
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;
|
||||||
@ -169,7 +158,6 @@ int *printf_number(int *argp, int length, bool sign, int radix)
|
|||||||
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:
|
||||||
@ -229,19 +217,16 @@ int *printf_number(int *argp, int length, bool sign, int radix)
|
|||||||
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]);
|
||||||
|
|
||||||
|
@ -2,4 +2,5 @@
|
|||||||
|
|
||||||
void putc(char c);
|
void putc(char c);
|
||||||
void puts(const char* str);
|
void puts(const char* str);
|
||||||
|
void puts_f(const char far* str);
|
||||||
void _cdecl printf(const char* fmt, ...);
|
void _cdecl printf(const char* fmt, ...);
|
@ -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
|
||||||
|
@ -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);
|
|
Loading…
x
Reference in New Issue
Block a user