Custom Freestanding printf only displaying one letter and random capital S

105 Views Asked by At

I am trying to develop my own kernel which I am booting to with GRUB.

In order to display strings with variables, I have started to develop my own printf(char*, ...) function.

Here is the kernel.cpp (thanks to Write Your Own Operating System YouTube tutorial for the main loading part (printf is my code entirely))

#include <stdarg.h>


#define VGA_BLACK 0
#define VGA_BLUE 1
#define VGA_GREEN 2
#define VGA_CYAN 3
#define VGA_RED 4
#define VGA_MAGENTA 5
#define VGA_BROWN 6
#define VGA_GREY 7
#define VGA_BRIGHT 8

#define VGA_DEFAULT_FG VGA_GREEN
#define VGA_DEFAULT_BG VGA_BLACK

volatile char* videoMemory = (volatile char*)0xB8000;
unsigned int color = ((VGA_DEFAULT_BG<<4) | (VGA_DEFAULT_FG & 0x0F));

void putchar(char c){
  *videoMemory++ = c;
  *videoMemory++ = color;
}

void printInt(int number){
  if(number <= 0){
    putchar('0');
    return;
  }
  int diget = number/10;
  char c = diget + 48;
  putchar(c);
  int newNum = diget%10;
  printInt(newNum);
}

int strlen(char* str){
  int len = 0;
  for(int i = 0; str[i] != '\0'; i++){
    len++;
  }
  return len;
}

void printf(char* msg, ...){
  va_list args;
  va_start(args, msg);
  for(int i = 0; i < strlen(msg); i++){
    if(msg[i] == '%'){
      i++;
      if(msg[i] == 'd'){
        i++;
        int res = va_arg(args, int);
        printInt(res);
      } else if(msg[i] == 's'){
        i++;
        char* c;
        do{
          c = va_arg(args, char*);

          putchar(*c);
        } while(c != '\n');
      } else {
        putchar('%');
      }
    } else {
      putchar(msg[i]);
    }
  }
  va_end(args);
}


void setColor(char fg, char bg){
  color = ((bg<<4) | (fg & 0x0F));
}


typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void callConstructors(){
  for(constructor* i = &start_ctors; i != &end_ctors; i++){
    (*i)();
  }
}

extern "C" void kernelMain(void* multibootStructure, unsigned int magicNumber){
  setColor(VGA_GREEN+VGA_BRIGHT, VGA_BLACK);
  printf("Booting %s", "Test System");
  while(true);
}

Result: enter image description here

As you can see, it displays the first character and 'S'.

If I were to change the message to "My Custom Kernel", this is the result:

enter image description here

As you can see here, it again prints the first letter and then 'S'.

Why is this happening? By my understanding, va_args changes char to int, however this does not explain why it only displays the first letter along with an 'S'.

Why is this happening and how can I fix this?

Edit: This has also been compiled with the flags: -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore

0

There are 0 best solutions below