Add: semi-working printf implementation
This commit is contained in:
3
io.h
3
io.h
@@ -1,7 +1,10 @@
|
|||||||
#ifndef INCLUDE_IO_H
|
#ifndef INCLUDE_IO_H
|
||||||
#define INCLUDE_IO_H
|
#define INCLUDE_IO_H
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
void outb(unsigned short port, unsigned char data);
|
void outb(unsigned short port, unsigned char data);
|
||||||
unsigned char inb(unsigned short port);
|
unsigned char inb(unsigned short port);
|
||||||
|
void x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
20
io.s
20
io.s
@@ -12,3 +12,23 @@ inb:
|
|||||||
mov dx, [esp + 4]
|
mov dx, [esp + 4]
|
||||||
in al, dx
|
in al, dx
|
||||||
ret
|
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
|
||||||
|
|||||||
Binary file not shown.
BIN
kernel.elf
BIN
kernel.elf
Binary file not shown.
3
kmain.c
3
kmain.c
@@ -8,7 +8,6 @@ int kmain(int retvalue)
|
|||||||
log("Kernel started", 2);
|
log("Kernel started", 2);
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
puts("hello\nbrave\nnew\nworld");
|
printf("Formatted: %% %c %s %d\n", 'f', "Hello", 77);
|
||||||
|
|
||||||
return retvalue;
|
return retvalue;
|
||||||
}
|
}
|
||||||
|
|||||||
20
stdint.h
Normal file
20
stdint.h
Normal file
@@ -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
|
||||||
189
stdio.c
189
stdio.c
@@ -1,6 +1,7 @@
|
|||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
char* fb = (char *) 0x000B8000;
|
char* fb = (char *) 0x000B8000;
|
||||||
const unsigned VGA_WIDTH = 80;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
17
stdio.h
17
stdio.h
@@ -1,6 +1,8 @@
|
|||||||
#ifndef INCLUDE_STDIO_H
|
#ifndef INCLUDE_STDIO_H
|
||||||
#define INCLUDE_STDIO_H
|
#define INCLUDE_STDIO_H
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
#define FB_GREEN 2
|
#define FB_GREEN 2
|
||||||
#define FB_DARK_GREY 8
|
#define FB_DARK_GREY 8
|
||||||
|
|
||||||
@@ -19,4 +21,19 @@ unsigned int getcolor(int x, int y);
|
|||||||
void scroll(int lines);
|
void scroll(int lines);
|
||||||
void putc(char c);
|
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
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user