Browse Source

:new: 完成了printk(暂不支持浮点数打印)

fslongjin 3 years ago
parent
commit
ead838bffd
8 changed files with 441 additions and 135 deletions
  1. 3 1
      .vscode/settings.json
  2. 17 9
      kernel/Makefile
  3. 0 0
      kernel/common/font.h
  4. 12 5
      kernel/common/glib.h
  5. 234 39
      kernel/common/printk.c
  6. 124 0
      kernel/common/printk.h
  7. 51 22
      kernel/main.c
  8. 0 59
      kernel/printk.h

+ 3 - 1
.vscode/settings.json

@@ -2,6 +2,8 @@
     "files.associations": {
         "stdlib.h": "c",
         "stdbool.h": "c",
-        "printk.h": "c"
+        "printk.h": "c",
+        "stdarg.h": "c",
+        "font.h": "c"
     }
 }

+ 17 - 9
kernel/Makefile

@@ -1,19 +1,27 @@
+SUBDIR_ROOTS := . common
+DIRS := . $(shell find $(SUBDIR_ROOTS) -type d)
+GARBAGE_PATTERNS := *.o *.s~ *.s *.S~ *.c~ *.h~ kernel *.a
+GARBAGE := $(foreach DIR,$(DIRS),$(addprefix $(DIR)/,$(GARBAGE_PATTERNS)))
 
 all: kernel
 	objcopy -I elf64-x86-64 -S -R  ".eh_frame" -R ".comment" -O binary kernel ../bin/kernel/kernel.bin
 
 
-kernel: head.o main.o
-	ld -b elf64-x86-64 -o kernel head.o main.o -T link.lds
-
-main.o: main.c
-# -fno-builtin: 不使用C语言内建函数
-# The -m64 option sets int to 32bits and long and pointer to 64 bits and generates code for AMD’s x86-64 architecture.
-	gcc -mcmodel=large -fno-builtin -m64 -c main.c
+kernel: head.o main.o printk.o
+	ld -b elf64-x86-64 -z muldefs -o kernel head.o main.o printk.o -T link.lds
 
 head.o: head.S
 	gcc -E head.S > head.s # 预处理
 	as --64 -o head.o head.s
 
-clean:
-	rm -rf *.o *.s~ *.s *.S~ *.c~ *.h~ kernel
+main.o: main.c 
+# -fno-builtin: 不使用C语言内建函数
+# The -m64 option sets int to 32bits and long and pointer to 64 bits and generates code for AMD’s x86-64 architecture.
+	gcc -mcmodel=large -fno-builtin -m64 -c main.c  -fno-stack-protector
+
+
+printk.o: common/printk.c
+	gcc -mcmodel=large -fno-builtin -m64 -c common/printk.c -fno-stack-protector
+
+clean: 
+	rm -rf $(GARBAGE)

+ 0 - 0
kernel/font.h → kernel/common/font.h


+ 12 - 5
kernel/glib.h → kernel/common/glib.h

@@ -4,9 +4,11 @@
 //
 
 #pragma once
+#ifndef GLIB_H
+#define GLIB_H
 
 //引入对bool类型的支持
-#include<stdbool.h>
+#include <stdbool.h>
 
 #define NULL 0
 
@@ -24,6 +26,8 @@
 #define io_lfence() __asm__ __volatile__("lfence\n\t" :: \
                                              : "memory") // 在lfence指令前的读操作当必须在lfence指令后的读操作前完成。
 
+#define ABS(x) ((x) > 0 ? (x) : -(x))   // 绝对值
+
 //链表数据结构
 struct List
 {
@@ -74,20 +78,21 @@ static inline void list_del(struct List *entry)
     entry->next = entry->prev;
 }
 
-static inline bool list_empty(struct List* entry)
+static inline bool list_empty(struct List *entry)
 {
     /**
      * @brief 判断循环链表是否为空
      * @param entry 入口
      */
 
-    if(entry->prev == entry->next)
+    if (entry->prev == entry->next)
         return true;
-    else return false;
+    else
+        return false;
 }
 
 //计算字符串的长度(经过测试,该版本比采用repne/scasb汇编的运行速度快16.8%左右)
-static inline int strlen(char* s)
+static inline int strlen(char *s)
 {
     register int __res = 0;
     while (s[__res] != '\0')
@@ -96,3 +101,5 @@ static inline int strlen(char* s)
     }
     return __res;
 }
+
+#endif

+ 234 - 39
kernel/printk.c → kernel/common/printk.c

@@ -3,7 +3,66 @@
 //
 #include "printk.h"
 #include <math.h>
+//#include "linkage.h"
 
+struct screen_info pos;
+
+void show_color_band(int width, int height, char a, char b, char c, char d)
+{
+    /** 向帧缓冲区写入像素值
+     * @param address: 帧缓存区的地址
+     * @param val:像素值
+     */
+
+    for (int i = 0; i < width * height; ++i)
+    {
+
+        *((char *)pos.FB_address + 0) = d;
+        *((char *)pos.FB_address + 1) = c;
+        *((char *)pos.FB_address + 2) = b;
+        *((char *)pos.FB_address + 3) = a;
+        ++pos.FB_address;
+    }
+}
+
+int calculate_max_charNum(int len, int size)
+{
+    /**
+     * @brief 计算屏幕上能有多少行
+     * @param len 屏幕长/宽
+     * @param size 字符长/宽
+     */
+    return len / size;
+}
+
+int init_printk(const int width, const int height, unsigned int *FB_address, const int FB_length, const int char_size_x, const int char_size_y)
+{
+
+    pos.width = width;
+    pos.height = height;
+    pos.char_size_x = char_size_x;
+    pos.char_size_y = char_size_y;
+    pos.max_x = calculate_max_charNum(width, char_size_x);
+    pos.max_y = calculate_max_charNum(height, char_size_y);
+
+    pos.FB_address = FB_address;
+    pos.FB_length = FB_length;
+
+    pos.x = 0;
+    pos.y = 0;
+
+    return 0;
+}
+
+static int set_printk_pos(const int x, const int y)
+{
+    // 指定的坐标不在屏幕范围内
+    if (!((x >= 0 && x <= pos.max_x) && (y >= 0 && y <= pos.max_y)))
+        return EPOS_OVERFLOW;
+    pos.x = x;
+    pos.y = y;
+    return 0;
+}
 int skip_and_atoi(const char **s)
 {
     /**
@@ -18,6 +77,22 @@ int skip_and_atoi(const char **s)
     }
     return ans;
 }
+
+void auto_newline()
+{
+    /**
+     * @brief 超过每行最大字符数,自动换行
+     * 
+     */
+    if (pos.x > pos.max_x)
+    {
+        pos.x = 0;
+        ++pos.y;
+    }
+    if (pos.y > pos.max_y)
+        pos.y = 0;
+}
+
 static int vsprintf(char *buf, const char *fmt, va_list args)
 {
     /**
@@ -53,11 +128,11 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
 
         //清空标志位和field宽度
         field_width = flags = 0;
-        ++fmt;
 
         bool flag_tmp = true;
         bool flag_break = false;
 
+        ++fmt;
         while (flag_tmp)
         {
             switch (*fmt)
@@ -67,13 +142,7 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
                 flag_break = true;
                 flag_tmp = false;
                 break;
-            case '%':
-                //输出 %
-                *str = '%';
-                ++str;
-                ++fmt;
-                flag_break = true;
-                break;
+
             case '-':
                 // 左对齐
                 flags |= LEFT;
@@ -107,13 +176,21 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
             break;
 
         //获取区域宽度
+        field_width = -1;
         if (*fmt == '*')
         {
             field_width = va_arg(args, int);
             ++fmt;
         }
         else if (is_digit(*fmt))
+        {
             field_width = skip_and_atoi(&fmt);
+            if (field_width < 0)
+            {
+                field_width = -field_width;
+                flags |= LEFT;
+            }
+        }
 
         //获取小数精度
         precision = -1;
@@ -137,29 +214,34 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
             qualifier = *fmt;
             ++fmt;
         }
+        //为了支持lld
+        if (qualifier == 'l' && *fmt == 'l', *(fmt + 1) == 'd')
+            ++fmt;
 
         //转化成字符串
-
+        long long *ip;
         switch (*fmt)
         {
+        //输出 %
+        case '%':
+            *str++ = '%';
+
+            break;
         // 显示一个字符
         case 'c':
             //靠右对齐
             if (!(flags & LEFT))
             {
-                while (--field_width)
+                while (--field_width > 0)
                 {
                     *str = ' ';
                     ++str;
                 }
             }
-            else //靠左对齐
-            {
-                *str = (char)va_arg(args, int);
-                ++str;
-                --field_width;
-            }
-            while (--field_width)
+
+            *str++ = (unsigned char)va_arg(args, int);
+
+            while (--field_width > 0)
             {
                 *str = ' ';
                 ++str;
@@ -208,10 +290,13 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
             break;
         //以八进制显示字符串
         case 'o':
+            flags |= SMALL;
+        case 'O':
+            flags |= SPECIAL;
             if (qualifier == 'l')
-                write_num(str, va_arg(args, long long), 8, field_width, precision, flags);
+                str = write_num(str, va_arg(args, long long), 8, field_width, precision, flags);
             else
-                write_num(str, va_arg(args, int), 8, field_width, precision, flags);
+                str = write_num(str, va_arg(args, int), 8, field_width, precision, flags);
             break;
 
         //打印指针指向的地址
@@ -222,7 +307,7 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
                 flags |= PAD_ZERO;
             }
 
-            write_num(str, (unsigned long)va_arg(args, void *), 16, field_width, precision, flags);
+            str = write_num(str, (unsigned long)va_arg(args, void *), 16, field_width, precision, flags);
 
             break;
 
@@ -230,34 +315,35 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
         case 'x':
             flags |= SMALL;
         case 'X':
+            flags |= SPECIAL;
             if (qualifier == 'l')
-                write_num(str, va_arg(args, long long), 16, field_width, precision, flags);
+                str = write_num(str, va_arg(args, long long), 16, field_width, precision, flags);
             else
-                write_num(str, va_arg(args, int), 16, field_width, precision, flags);
+                str = write_num(str, va_arg(args, int), 16, field_width, precision, flags);
             break;
 
         //打印十进制有符号整数
         case 'i':
         case 'd':
-        case 'ld':
+
             flags |= SIGN;
             if (qualifier == 'l')
-                write_num(str, va_arg(args, long long), 10, field_width, precision, flags);
+                str = write_num(str, va_arg(args, long long), 10, field_width, precision, flags);
             else
-                write_num(str, va_arg(args, int), 10, field_width, precision, flags);
+                str = write_num(str, va_arg(args, int), 10, field_width, precision, flags);
             break;
 
         //打印十进制无符号整数
         case 'u':
             if (qualifier == 'l')
-                write_num(str, va_arg(args, unsigned long long), 10, field_width, precision, flags);
+                str = write_num(str, va_arg(args, unsigned long long), 10, field_width, precision, flags);
             else
-                write_num(str, va_arg(args, unsigned int), 10, field_width, precision, flags);
+                str = write_num(str, va_arg(args, unsigned int), 10, field_width, precision, flags);
             break;
 
         //输出有效字符数量到*ip对应的变量
         case 'n':
-            long long *ip;
+
             if (qualifier == 'l')
                 ip = va_arg(args, long long *);
             else
@@ -269,18 +355,20 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
         //对于不识别的控制符,直接输出
         default:
             *str++ = '%';
-            if(*fmt)
+            if (*fmt)
                 *str++ = *fmt;
-            else --fmt;
+            else
+                --fmt;
             break;
         }
     }
     *str = '\0';
+
     //返回缓冲区已有字符串的长度。
-    return str-buf;
+    return str - buf;
 }
 
-static void write_num(char *str, long long num, int base, int field_width, int precision, int flags)
+static char *write_num(char *str, long long num, int base, int field_width, int precision, int flags)
 {
     /**
      * @brief 将数字按照指定的要求转换成对应的字符串
@@ -296,7 +384,6 @@ static void write_num(char *str, long long num, int base, int field_width, int p
     // 首先判断是否支持该进制
     if (base < 2 || base > 36)
         return 0;
-
     char pad, sign, tmp_num[100];
 
     const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -335,11 +422,11 @@ static void write_num(char *str, long long num, int base, int field_width, int p
         tmp_num[js_num++] = '0';
     else
     {
-        num = abs(num);
+        num = ABS(num);
         //进制转换
-        while (num)
+        while (num > 0)
         {
-            tmp_num[js_num++] = num % base; // 注意这里,输出的数字,是小端对齐的。低位存低位
+            tmp_num[js_num++] = digits[num % base]; // 注意这里,输出的数字,是小端对齐的。低位存低位
             num /= base;
         }
     }
@@ -351,7 +438,7 @@ static void write_num(char *str, long long num, int base, int field_width, int p
 
     // 靠右对齐
     if (!(flags & LEFT))
-        while (field_width--)
+        while (field_width-- > 0)
             *str++ = pad;
 
     if (sign)
@@ -371,11 +458,119 @@ static void write_num(char *str, long long num, int base, int field_width, int p
         *str++ = '0';
     }
 
-    while (js_num--)
+    while (js_num-- > 0)
         *str++ = tmp_num[js_num];
+    
 
-    while (field_width--)
+    while (field_width-- > 0)
         *str++ = ' ';
 
     return str;
+}
+
+static void putchar(unsigned int *fb, int Xsize, int x, int y, unsigned int FRcolor, unsigned int BKcolor, unsigned char font)
+{
+    /**
+     * @brief 在屏幕上指定位置打印字符
+     * 
+     * @param fb 帧缓存线性地址
+     * @param Xsize 行分辨率
+     * @param x 左上角列像素点位置
+     * @param y 左上角行像素点位置
+     * @param FRcolor 字体颜色
+     * @param BKcolor 背景颜色
+     * @param font 字符的bitmap
+     */
+
+    unsigned char *font_ptr = font_ascii[font];
+    unsigned int *addr;
+
+    int testbit; // 用来测试某位是背景还是字体本身
+
+    for (int i = 0; i < pos.char_size_y; ++i)
+    {
+        // 计算出帧缓冲区的地址
+        addr = fb + Xsize * (y + i) + x;
+        testbit = (1 << (pos.char_size_x + 1));
+        for (int j = 0; j < pos.char_size_x; ++j)
+        {
+            //从左往右逐个测试相应位
+            testbit >>= 1;
+            if (*font_ptr & testbit)
+                *addr = FRcolor; // 字,显示前景色
+            else
+                *addr = BKcolor; // 背景色
+
+            ++addr;
+        }
+        ++font_ptr;
+    }
+}
+
+int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ...)
+{
+    /**
+     * @brief 格式化打印字符串
+     * 
+     * @param FRcolor 前景色
+     * @param BKcolor 背景色
+     * @param ... 格式化字符串
+     */
+
+    va_list args;
+    va_start(args, fmt);
+
+    int len = vsprintf(buf, fmt, args);
+
+    va_end(args);
+    unsigned char current;
+
+    int i; // 总共输出的字符数
+    for (i = 0; i < len; ++i)
+    {
+        current = *(buf + i);
+        //输出换行
+        if (current == '\n')
+        {
+            pos.x = 0;
+            ++pos.y;
+        }
+        else if (current == '\t') // 输出制表符
+        {
+            int space_to_print = 8 - pos.x % 8;
+
+            while (space_to_print--)
+            {
+                putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, BLACK, BLACK, ' ');
+                ++pos.x;
+
+                auto_newline();
+            }
+        }
+        else if (current == '\b') // 退格
+        {
+            --pos.x;
+            if (pos.x < 0)
+            {
+                --pos.y;
+                if (pos.y <= 0)
+                    pos.x = pos.y = 0;
+                else
+                    pos.x = pos.max_x;
+            }
+
+            putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, ' ');
+            ++pos.x;
+
+            auto_newline();
+        }
+        else
+        {
+            putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, current);
+            ++pos.x;
+            auto_newline();
+        }
+    }
+
+    return i;
 }

+ 124 - 0
kernel/common/printk.h

@@ -0,0 +1,124 @@
+//
+// Created by longjin on 2022/1/21.
+//
+#pragma once
+#ifndef PRINTK_H
+#define PRINTK_H
+
+#define PAD_ZERO 1 // 0填充
+#define LEFT 2     // 靠左对齐
+#define RIGHT 4    // 靠右对齐
+#define PLUS 8     // 在正数前面显示加号
+#define SPACE 16
+#define SPECIAL 32 // 在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
+#define SMALL 64   // 十进制以上数字显示小写字母
+#define SIGN 128   // 显示符号位
+
+#define is_digit(c) ((c) >= '0' && (c) <= '9') // 用来判断是否是数字的宏
+
+// 字体颜色的宏定义
+#define WHITE 0x00ffffff  //白
+#define BLACK 0x00000000  //黑
+#define RED 0x00ff0000    //红
+#define ORANGE 0x00ff8000 //橙
+#define YELLOW 0x00ffff00 //黄
+#define GREEN 0x0000ff00  //绿
+#define BLUE 0x000000ff   //蓝
+#define INDIGO 0x0000ffff //靛
+#define PURPLE 0x008000ff //紫
+
+// 异常的宏定义
+#define EPOS_OVERFLOW 1 // 坐标溢出
+#define EFB_MISMATCH 2  // 帧缓冲区与指定的屏幕大小不匹配
+
+#include "font.h"
+#include "glib.h"
+//#include "linkage.h"
+#include <stdarg.h>
+
+struct screen_info
+{
+    int width, height; //屏幕大小
+
+    int max_x, max_y; // 最大x、y字符数
+
+    int x, y; //光标位置
+
+    int char_size_x, char_size_y;
+
+    unsigned int *FB_address; //帧缓冲区首地址
+    unsigned long FB_length;  // 帧缓冲区长度
+};
+
+
+extern unsigned char font_ascii[256][16]; //导出ascii字体的bitmap(8*16大小) ps:位于font.h中
+
+char buf[4096]; //vsprintf()的缓冲区
+
+/**
+ * @brief 初始化printk的屏幕信息
+ * 
+ * @param width 屏幕宽度
+ * @param height 屏幕高度
+ * @param FB_address 帧缓冲区地址
+ * @param FB_length 帧缓冲区长度
+ * @param char_size_x 字符的列坐标
+ * @param char_size_y 字符的行坐标
+ */
+int init_printk(const int width, const int height, unsigned int *FB_address, const int FB_length, const int char_size_x, const int char_size_y);
+/**
+ * @brief Set the printk pos object
+ * 
+ * @param x 列坐标
+ * @param y 行坐标
+ */
+static int set_printk_pos(const int x, const int y);
+/**
+ * @brief 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中
+ * 
+ * @param buf 结果缓冲区
+ * @param fmt 格式化字符串
+ * @param args 内容
+ * @return 最终字符串的长度
+ */
+static int vsprintf(char *buf, const char *fmt, va_list args);
+
+/**
+ * @brief 将数字按照指定的要求转换成对应的字符串(2~36进制)
+ * 
+ * @param str 要返回的字符串
+ * @param num 要打印的数值
+ * @param base 基数
+ * @param field_width 区域宽度 
+ * @param precision 精度
+ * @param flags 标志位
+ */
+static char* write_num(char *str, long long num, int base, int field_width, int precision, int flags);
+
+/**
+ * @brief 在屏幕上指定位置打印字符
+ * 
+ * @param fb 帧缓存线性地址
+ * @param Xsize 行分辨率
+ * @param x 左上角列像素点位置
+ * @param y 左上角行像素点位置
+ * @param FRcolor 字体颜色
+ * @param BKcolor 背景颜色
+ * @param font 字符的bitmap
+ */
+static void putchar(unsigned int *fb, int Xsize, int x, int y, unsigned int FRcolor, unsigned int BKcolor, unsigned char font);
+
+/**
+ * @brief 格式化打印字符串
+ * 
+ * @param FRcolor 前景色
+ * @param BKcolor 背景色
+ * @param ... 格式化字符串
+ */
+
+
+#define printk(...) printk_color( WHITE, BLACK, __VA_ARGS__ )
+
+int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char*fmt, ...);
+
+#endif

+ 51 - 22
kernel/main.c

@@ -1,40 +1,69 @@
 //
 // Created by longjin on 2022/1/20.
 //
-int *address = (int *)0xffff800000a00000; //帧缓存区的地址
 
-void show_color_band(int width, int height, char a, char b, char c, char d)
+#include "common/glib.h"
+#include "common/printk.h"
+
+int *FR_address = (int *)0xffff800000a00000; //帧缓存区的地址
+
+void show_welcome()
 {
-    /** 向帧缓冲区写入像素值
-     * @param address: 帧缓存区的地址
-     * @param val:像素值
+    /**
+     * @brief 打印欢迎页面
+     * 
      */
 
-    for (int i = 0; i < width * height; ++i)
-    {
-
-        *((char *)address + 0) = d;
-        *((char *)address + 1) = c;
-        *((char *)address + 2) = b;
-        *((char *)address + 3) = a;
-        ++address;
-    }
+    printk("\n\n");
+    for (int i = 0; i < 74; ++i)
+        printk(" ");
+    printk_color(0x00e0ebeb, 0x00e0ebeb, "                                \n");
+    for (int i = 0; i < 74; ++i)
+        printk(" ");
+    printk_color(BLACK, 0x00e0ebeb, "      Welcome to DragonOS !     \n");
+    for (int i = 0; i < 74; ++i)
+        printk(" ");
+    printk_color(0x00e0ebeb, 0x00e0ebeb, "                                \n");
 }
 
-//操作系统内核从这里开始执行
-void Start_Kernel(void)
+void test_printk()
 {
-    
+    //测试直接输出
+    printk("\nTesting printk...\n");
+    //测试输出单个字符
+    printk("%c\n", 't');
+    //测试输出字符串%s
+    printk("%s\n", "xxx");
 
-    
+    //测试输出数字
+    printk("%d %ld %lld\n", 1, 2, 3);
 
-    show_color_band(1440, 20, 0x00, 0xff, 0x00, 0x00);
+    //测试输出两个百分号
+    printk("%%\n");
 
-    show_color_band(1440, 20, 0x00, 0x00, 0xff, 0x00);
+    //测试输出\t
+    printk("\nTesting tab...\n");
+    printk("date\t\tname\tscore\n");
+    printk("2022-01-01\tDavid\t99\n");
+    printk("2022-01-01\tJohn\t95\n");
 
-    show_color_band(1440, 20, 0x00, 0x00, 0x00, 0xff);
 
-    show_color_band(1440, 20, 0x00, 0xff, 0xff, 0xff);
+    //测试输出八进制
+    printk("\nTest base 8 : %d --> %o\n", 255, 255);
+
+    //测试输出十六进制
+    printk("\nTest base 16 : %d --> %x\n", 255, 255);
+    printk("\nTest base 16 : %d --> %X\n", 255, 255);
+}
+//操作系统内核从这里开始执行
+void Start_Kernel(void)
+{
+    // 初始化printk
+    init_printk(1440, 900, FR_address, 1440 * 900 * 4, 8, 16);
+
+    show_welcome();
+    test_printk();
+    
 
     while (1)
         ;

+ 0 - 59
kernel/printk.h

@@ -1,59 +0,0 @@
-//
-// Created by longjin on 2022/1/21.
-//
-#pragma once
-
-#define PAD_ZERO 1  // 0填充
-#define LEFT 2      // 靠左对齐
-#define RIGHT 4     // 靠右对齐
-#define PLUS 8      // 在正数前面显示加号
-#define SPACE 16
-#define SPECIAL 32  // 在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
-#define SMALL 64    // 十进制以上数字显示小写字母
-#define SIGN 128    // 显示符号位
-
-
-#define is_digit(c) ((c) >= '0' && (c) <= '9') // 用来判断是否是数字的宏
-
-#include "font.h"
-#include "glib.h"
-#include <stdarg.h>
-
-struct screen_info
-{
-    int width, height; //屏幕大小
-
-    int x, y; //光标位置
-
-    int char_size_x, char_size_y;
-
-    unsigned int *FB_address; //帧缓冲区首地址
-    unsigned long FB_length;  // 帧缓冲区长度
-} pos;
-
-extern unsigned char font_ascii[256][16]; //导出ascii字体的bitmap(8*16大小)
-
-char buf[4096]; //vsprintf()的缓冲区
-
-
-/**
-     * 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中
-     * @param buf 结果缓冲区
-     * @param fmt 格式化字符串
-     * @param args 内容
-     * @return 最终字符串的长度
-     */
-static int vsprintf(char *buf, const char *fmt, va_list args);
-
-
-/**
- * @brief 将数字按照指定的要求转换成对应的字符串(2~36进制)
- * 
- * @param str 要返回的字符串
- * @param num 要打印的数值
- * @param base 基数
- * @param field_width 区域宽度 
- * @param precision 精度
- * @param flags 标志位
- */
-static void write_num(char* str, long long num, int base, int field_width, int precision, int flags);