Я пытаюсь разработать свое собственное ядро, к которому загружаюсь с GRUB.
Чтобы отобразить строки с переменными, я начал разрабатывать свою собственную функцию printf(char*, ...)
.
Вот kernel.cpp (спасибо Пишите свою собственную операционную систему YouTube учебник для основной части загрузки (printf - мой код целиком))
#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);
}
Результат:
Как видите, он отображает первый символ и 'S'.
Если бы я изменил сообщение на «Мое собственное ядро», эторезультат:
Как вы можете видеть здесь, он снова печатает первую букву, а затем 'S'.
Почему этопроисходит?Насколько я понимаю, va_args меняет char
на int
, однако это не объясняет, почему он отображает только первую букву вместе с буквой S.
Почему это происходит и как я могу это исправить?
Редактировать: Это также было скомпилировано с флагами: -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore