博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
十八、可以输出文字了
阅读量:6938 次
发布时间:2019-06-27

本文共 21624 字,大约阅读时间需要 72 分钟。

hot3.png

    那个点阵字库数组这么大,占地方,难看。而且要换字体也不方便,还得重新制作。还是直接把现有的字库文件作为一个资源文件比较好,loadre 到内存就行。

    字库暂时放到内存 0x10000处

; const.inc; 常量; 四彩; 2015-12-12%ifndef _CONSTANT_INC%define _CONSTANT_INC; ========================================================================================; 内存中 0x0500 ~ 0x7BFF 段(29.75 KB)和 0x7E00 ~ 0x9FBFF 段(607.5 KB)可自由使用。; 引导扇区段在加载完 Loader 后也可使用,即整个 0x500 ~ 0x9FBFF 段(637.25 KB)都可自由使用。;STACKSIZE           equ 0x1000          ; 堆栈大小SEGMENTOFGPARAM     equ 0x50            ; 存放全局数据的段基址SEGMENTOFTEMP       equ 0x7E            ; 临时数据被加载到内存的段基址SEGMENTOFFONT       equ 0x1000          ; 点阵字库被加载到内存的段基址SEGMENTOFLOADER     equ 0x9000          ; LOADER.SYS 被加载到内存的段基址SEGMENTOFKERNEL     equ 0x8000          ; KERNEL.EXE 被加载到内存的段基址KERNELENTRYPHYADDR  equ 0x30400         ; kernel 的程序入口的物理地址                                        ; 必须与 Makefile 中 -Ttext 参数的值相等; ****************************************************************************************%endif
; loader.asm; 加载程序; 四彩; 2015-12-12; ========================================================================================; ----------------------------------------------------------------------------------------; 头文件%include "./boot/inc/const.inc"%include "./boot/inc/FAT12.inc"%include "./boot/inc/PMode.inc"%include "./boot/inc/ELF.inc"; ----------------------------------------------------------------------------------------    org STACKSIZE    jmp RMode_main; ****************************************************************************************;=========================================================================================[SECTION .data]; ----------------------------------------------------------------------------------------; 地址范围描述符结构(Address Range Descriptor Structure)struc T_AddrRngDscStruc;      字段名                       ;偏移 长度 说明    .dwBaseAddrLow      resd 1      ; 0x00  4   基地址的低 32 位    .dwBaseAddrHigh     resd 1      ; 0x04  4   基地址的高 32 位(未使用,为 0)    .dwLengthLow        resd 1      ; 0x08  4   长度(字节)的低32位    .dwLengthHigh       resd 1      ; 0x0C  4   长度(字节)的高32位(未使用,为 0)    .dwType             resd 1      ; 0x10  4   地址类型:1 = 可用段, 2 = 正用或保留段,endstruc; 全局变量结构struc T_Global_Param;      字段名                       ;偏移 长度 说明    .dwMemorySize       resd 1      ; 0x00  4   内存总容量    .dwPhyAddrOfVideo   resd 1      ; 0x04  4   显存基址    .wScreenX           resw 1      ; 0x08  2   分辨率 X    .wScreenY           resw 1      ; 0x0A  2   分辨率 Y    .bBitsPerPixel      resb 1      ; 0x0C  1   颜色数endstruc; ----------------------------------------------------------------------------------------; 出错提示信息及 kernel 文件名    strCheckMemoryFail  db "Failed to check memory", 0    strNotSupportVESA   db "Not support VESA", 0    strNotFoundFile     db "Not found ", 0    FileNameOfKernel    db "KERNEL  SYS", 0     ; kernel 文件名(8 + 3 格式)    FileNameOfFont      db "ASC16      ", 0     ; 点阵字库文件名; ----------------------------------------------------------------------------------------tArds istruc T_AddrRngDscStruc      ; 地址范围描述符结构实体    times T_AddrRngDscStruc_size db 0iend; ----------------------------------------------------------------------------------------; GDT; Loader 把全部内存都作为一个段使用,分为两类:代码段、数据段;                       基址        界限        属性Desc_Begin : Descriptor 0,          0,          0                           ; 空描述符Desc_Code  : Descriptor 0,          0xFFFFF,    DA_CS_ER + DA_32 + DA_4K    ; 代码段Desc_Data  : Descriptor 0,          0xFFFFF,    DA_DS_RW + DA_32 + DA_4K    ; 数据段Desc_End   :; ----------------------------------------------------------------------------------------; GDTPtrGDTPtr  dw Desc_End - Desc_Begin - 1            ; 界限        dd SEGMENTOFLOADER * 0x10 + Desc_Begin  ; 基址; ----------------------------------------------------------------------------------------; 选择子SelectorCode    equ Desc_Code  - Desc_BeginSelectorData    equ Desc_Data  - Desc_Begin; ****************************************************************************************; ========================================================================================[SECTION .code16][BITS 16]; 实模式代码段:取得内存容量、复制 kernel 到内存、设定画面模式、开启保护模式; ----------------------------------------------------------------------------------------RMode_main:    ; 初始化寄存器    mov ax, cs    mov ds, ax    mov ss, ax    mov ax, STACKSIZE    mov bp, ax    mov sp, ax    ; 获取内存信息    ; BIOS 中断 int 0x15    ; 入口参数:eax = 0xE820 功能号    ;           ebx = ARDS 所需的后续值,第一个为 0    ;           es : di = 内存缓冲区基址,指向一个地址范围描述符结构(ARDS)    ;           ecx = ARDS 的大小,通常 BIOS 总是填充 20 字节的信息到 ARDS 中    ;           edx = “SMAP” 的 ASCII 码(0x0534D4150)    ; 出口参数:CF 置 1 表明调用出错,否则无错    ;           eax = "SMAP" 的 ASCII 码    ;           ebx = 下一 ARDS 所需的后续值,如果为 0 则说明已到最后一个 ARDS。    push SEGMENTOFGPARAM    pop fs    xor ebx, ebx    mov di, tArds.MemChkLoop:    mov eax, 0xE820    mov ecx, T_AddrRngDscStruc_size    mov edx, 0x534D4150    int 15h    jnc .MemChkOK    mov si, strCheckMemoryFail    call PrintStr    jmp $.MemChkOK:    mov eax, [tArds + T_AddrRngDscStruc.dwLengthLow]    ; 累加内存总容量    add [fs : T_Global_Param.dwMemorySize], eax    cmp ebx, 0    jne .MemChkLoop    ; 复制 Kernel 到内存    mov si, FileNameOfKernel                ; 寻找    call SearchFile    cmp ax, 0    jnz .LoadKernel    mov si, strNotFoundFile    call PrintStr    mov si, FileNameOfKernel    call PrintStr    jmp $.LoadKernel:    push SEGMENTOFKERNEL                    ; 复制    pop es    xor bx, bx    call LoadFile    ; 复制字库到内存    mov si, FileNameOfFont    call SearchFile    cmp ax, 0    jnz .LoadFont    mov si, strNotFoundFile    call PrintStr    mov si, FileNameOfFont    call PrintStr    jmp $.LoadFont:    push SEGMENTOFFONT    pop es    xor bx, bx    call LoadFile   ; 设置图形模式    push SEGMENTOFTEMP                    ; 取得 VBE 信息    pop es    xor di, di    mov ax, 0x4F00    int 0x10    mov di, 0x200    mov ax, 0x4F01                          ; 取得 800*600*16 模式信息    mov cx, 0x114    int 0x10    cmp ax, 0x004F    jz .Support    mov si, strNotSupportVESA    call PrintStr    jmp $.Support:    mov ax, 0x4F02                          ; 设置画面模式    mov bx, 0x4114                          ; 800 * 600,16 位色,线性帧缓冲区    int 0x10    ; 保存显存相关信息到全局变量    mov eax, [es : 0x200 + 0x28]    mov [fs : T_Global_Param.dwPhyAddrOfVideo], eax    mov ax, [es : 0x200 + 0x12]    mov [fs : T_Global_Param.wScreenX], ax    mov ax, [es : 0x200 + 0x14]    mov [fs : T_Global_Param.wScreenY], ax    mov al, [es : 0x200 + 0x19]    mov [fs : T_Global_Param.bBitsPerPixel], al    ; 开启保护模式    lgdt [GDTPtr]                           ; 加载 GDT    in al, 0x92                             ; 打开地址线 A20    or al, 0b10    out 0x92, al    mov eax, cr0                            ; 置保护模式标志位    or eax, 1    mov cr0, eax    jmp dword SelectorCode : (SEGMENTOFLOADER * 0x10 + PMode_main)  ; 跳转至保护模式代码段; ----------------------------------------------------------------------------------------; 包含 FAT12 子函数    IncludeFAT12Function SEGMENTOFTEMP; ****************************************************************************************; ========================================================================================[SECTION .code32][BITS 32]; 保护模式代码段,由实模式跳入:重定位 kernel,跳转到 kernel; ----------------------------------------------------------------------------------------PMode_main:    ; 初始化寄存器    mov ax, SelectorData    mov ds, ax    mov ss, ax    mov es, ax    mov fs, ax    mov gs, ax    mov eax, SEGMENTOFLOADER * 0x10 + STACKSIZE    mov ebp, eax    mov esp, eax    ; 装载 kernel 各段(重定位)    xor ecx, ecx    mov cx, [SEGMENTOFKERNEL * 0x10 + Tag_ELF_Header.e_phnum]   ; 段数    mov esi, [SEGMENTOFKERNEL * 0x10 + Tag_ELF_Header.e_phoff]  ; 指向程序头表    add esi, SEGMENTOFKERNEL * 0x10.Load:    mov eax, [esi + Tag_Program_Header.p_type]                  ; 只装载可装载段    cmp eax, PT_LOAD    jnz .NotNeedLoad    push dword[esi + Tag_Program_Header.p_filesz]    mov eax, [esi + Tag_Program_Header.p_offset]    add eax, SEGMENTOFKERNEL * 0x10    push eax    push dword[esi + Tag_Program_Header.p_vaddr]    call memcpy    add esp, 3 * 4.NotNeedLoad:    add esi, Tag_ELF_Header.e_phentsize    loop .Load    ; 跳转至 kernel(修改 cs 和 eip)    jmp SelectorCode : KERNELENTRYPHYADDR; ----------------------------------------------------------------------------------------; 函数功能:内存复制; void memcpy(void *pDest, void *pSrc, DWORD dwSize);; 入口参数:es : pDest = 目标内存地址;           ds : pSrc  = 源内存地址;           dwSize     = 数据长度(字节); 出口参数:无memcpy:    push ebp    mov ebp, esp    push esi    push edi    push ecx    mov edi, [ebp + 2 * 4]                  ; pDest    mov esi, [ebp + 3 * 4]                  ; pSrc    mov ecx, [ebp + 4 * 4]                  ; dwSize    jecxz .Return.Copy:    lodsb    stosb    loop .Copy.Return:    pop ecx    pop edi    pop esi    mov esp, ebp    pop ebp    ret; ****************************************************************************************

    显示文字其实也是画图,把显示文字的函数也放到 graphics.c 里,只是头文件单列出来

/*  graphics.c    图形相关全局变量及函数	函数被分配到两个头文件:graphics.h(绘图)、io.h(文字)    四彩    2015-12-12*/#include "../lib/include/stddef.h"#include "../lib/include/string.h"#include "../kernel/include/graphics.h"#include "../kernel/include/io.h"// =======================================================================================// 全局参数// ---------------------------------------------------------------------------------------// 图形函数相关全局参数static unsigned short *pVideo, Color = 0;           // 显存地址和当前颜色static unsigned short Screen_X, Screen_Y;           // 屏幕分辨率static unsigned char BytePerPix;                    // 每个像素占用的位数// ---------------------------------------------------------------------------------------// 文字函数相关全局参数static unsigned char *pFont;                        // 点阵字库的物理内存地址static unsigned char WidthPerChar, HeightPerChar;   // 每个字符的宽度和高度// ***************************************************************************************// =======================================================================================// 函数// ---------------------------------------------------------------------------------------// 图形部分/*  画一条线*/void line(unsigned x0, unsigned y0, unsigned x1, unsigned y1){    int x, y;    if(x0 == x1)        for(y = y0; y <= y1; y++)            pVideo[Screen_X * y + x] = Color;    else if(x0 < x1)        for(x = x0; x <= x1; x++)        {            y = ((x - x0) * y1 + (x1 - x) * y0) / (x1 - x0);            pVideo[Screen_X * y + x] = Color;        }    else // if(x0 > x1)        for(x = x1; x <= x0; x++)        {            y = ((x0 - x) * y1 + (x - x1) * y0) / (x0 - x1);            pVideo[Screen_X * y + x] = Color;        }}/*  画一个方框并填色*/void rectangle(unsigned x0, unsigned y0, unsigned x1, unsigned y1){    unsigned x, y;    for(y = y0; y <= y1; y++)        for(x = x0; x <= x1; x++)            pVideo[Screen_X * y + x] = Color;}// ---------------------------------------------------------------------------------------// 文字部分/*  函数功能:显示一个字符    参数表:x, y = 屏幕起始坐标            ch  = 字符    返回值:无*/void putc(unsigned x, unsigned y, char ch){    int i, j, k;    k = HeightPerChar * ch;    for(i = 0; i < HeightPerChar; i++)        for(j = 0; j < WidthPerChar; j++)            if(pFont[k + i] & (1 << (7 - j)))                pVideo[Screen_X * (y + i) + x + j] = Color;}/*  函数功能:显示字符串    参数表:x, y = 屏幕起始坐标            str = 字符串    返回值:无*/void puts(unsigned x, unsigned y, char *str){    int i, j, k;    while(*str != NUL)    {        k = HeightPerChar * (*str);        for(i = 0; i < HeightPerChar; i++)            for(j = 0; j < WidthPerChar; j++)                if(pFont[k + i] & (1 << (7 - j)))                    pVideo[Screen_X * (y + i) + x + j] = Color;        str++;        x += WidthPerChar;    }}// ---------------------------------------------------------------------------------------// 设置参数部分/*	初始化图形参数*/void InitGraphics(GRAPHICS_PARAM *ptGraphics){    pVideo     = (unsigned short *)ptGraphics->dwPhyAddrOfVideo;    Screen_X   = ptGraphics->wScreenX;    Screen_Y   = ptGraphics->wScreenY;    BytePerPix = ptGraphics->bBitsPerPixel;}/*	设置颜色*/void SetColor(unsigned color){    Color = color;}/*  函数功能:设置字体    参数表:addr   = 点阵字库的物理内存地址           width  = 点阵字的宽度(像素)           height = 点阵字的高度(像素)    返回值:无*/void SetFont(unsigned addr, unsigned char width, unsigned char height){    pFont         = (unsigned char *)addr;    WidthPerChar  = width;    HeightPerChar = height;}// ---------------------------------------------------------------------------------------// 输出当前参数部分unsigned GetScreenX(){    return Screen_X;}unsigned GetScreenY(){    return Screen_Y;}// ***************************************************************************************
/*	io.h	输入输出函数,输出部分的实现在 graphics.c 内	四彩	2015-12-12*/#ifndef _IO_H#define _IO_H/*  函数功能:显示一个字符    参数表:x, y = 屏幕起始坐标            ch   = 字符    返回值:无*/void putc(unsigned x, unsigned y, char ch);/*	函数功能:显示字符串	参数表:x, y = 屏幕起始坐标			str  = 字符串	返回值:无*/void puts(unsigned x, unsigned y, char *str);/*  函数功能:设置字体    参数表:addr   = 点阵字库的物理内存地址           width  = 点阵字的宽度(像素)           height = 点阵字的高度(像素)    返回值:无*/void SetFont(unsigned addr, unsigned char width, unsigned char height);#endif

   用到几个处理字符串的函数,自己实现就行 —— C语言干这个手到擒来。顺手把可能会用到的都实现了

/*  string.h    字符串处理函数    四彩    2015-12-12*/#ifndef _STRING_H#define _STRING_H/*  函数功能:内存复制    参数表:pDst  = 目标内存地址           pSrc  = 源内存地址           nSzie = 要复制的长度(字节单位)    返回值:指向目标内存地址的指针*/void *memcpy(void *pDst, const void *pSrc, unsigned int nSzie);/*  函数功能:取字符串长度    参数表:pStr = 字符串地址    返回值:字符串长度*/unsigned strlen(const char *pStr);/*  函数功能:字符串比较    参数表:pStr1 = 字符串 1 地址           pStr2 = 字符串 2 地址    返回值:当 pStr1 < pStr2 时,返回为负数           当 pStr1 = pStr2 时,返回值 0           当 pStr1 > pStr2 时,返回正数*/int strcmp(const char *pStr1, const char *pStr2);/*  函数功能:复制字符串    参数表:pDst  = 目标字符串地址           pSrc  = 源字符串地址    返回值:指向目标字符串的指针*/char *strcpy(char *pDst, const char *pSrc);/*  函数功能:合并字符串    参数表:pDst  = 目标字符串地址           pSrc  = 源字符串地址    返回值:指向目标字符串的指针*/char *strcat(char *pDst, const char *pSrc);/*  函数功能:反转字符串    参数表:string = 字符串的地址    返回值:指向字符串的指针*/char *strrev(char *string);/*  函数功能:将整数转换为字符串    参数表:value  = 欲转换的数据           string = 目标字符串的地址           radix  = 转换后的进制数    返回值:指向字符串的指针*/char *itoa(int value, char *string, int radix);/*  函数功能:将无符号整数转换为字符串    参数表:value  = 欲转换的数据           string = 目标字符串的地址           radix  = 转换后的进制数    返回值:指向字符串的指针*/char *utoa(unsigned value, char *string, int radix);#endif
/*  string.c    字符串处理函数    四彩    2015-12-12*/#include "../lib/include/string.h"#include "../lib/include/stddef.h"/*  函数功能:内存复制    参数表:pDst  = 目标内存地址            pSrc  = 源内存地址            nSzie = 要复制的长度(字节单位)    返回值:指向目标内存地址的指针*/void *memcpy(void *pDst, const void *pSrc, unsigned nSzie){    // 不清楚来源结构,只能逐字节复制    unsigned char *p1 = (unsigned char *)pDst;    unsigned char *p2 = (unsigned char *)pSrc;    // 若目标内存与源内存完全一致,则无需复制    if(p1 == p2 || NULL == p1 || NULL == p2)        return(pDst);    // 若目标内存与源内存无重叠,或目标内存尾部与源内存头部重叠,则顺序复制    else if(p1 >= (p2 + nSzie) || p1 < p2)        while(nSzie--)            *p1++ = *p2++;    // 若目标内存头部与源内存尾部重叠,则逆序复制    else // if(p1 > p2 && p1 < (p2 + nSzie))    {        p1 += nSzie - 1;        p2 += nSzie - 1;        while(nSzie--)            *p1-- = *p2--;    }    return pDst;}/*  函数功能:取字符串长度    参数表:pStr = 字符串地址    返回值:字符串长度*/unsigned strlen(const char *pStr){    unsigned len = 0;    if(NULL == pStr)        return 0;    while(NUL != *pStr)    {        pStr++;        len++;    }    return len;}/*  函数功能:字符串比较    参数表:pStr1 = 字符串 1 地址            pStr2 = 字符串 2 地址    返回值:当 pStr1 < pStr2 时,返回为负数            当 pStr1 = pStr2 时,返回值 0            当 pStr1 > pStr2 时,返回正数*/int strcmp(const char *pStr1, const char *pStr2){    // 转无符号,进行 ASCII 编码比较    unsigned char *s1 = (unsigned char *)pStr1, *s2 = (unsigned char *)pStr2;    if(pStr1 == pStr2)              // 包含了两个都是空指针的情况        return 0;    else if(NULL == pStr1 && NULL != pStr2)        return -1;    else if(NULL != pStr1 && NULL == pStr2)        return 1;    for(; *s1 == *s2; ++s1, ++s2)        if(NUL == *s1)            return 0;    return(*s1 < *s2 ? -1 : 1);}/*  函数功能:复制字符串    参数表:pDst  = 目标字符串地址            pSrc  = 源字符串地址    返回值:指向目标字符串的指针*/char *strcpy(char *pDst, const char *pSrc){    char *p1 = pDst;    if(NULL == pDst || NULL == pSrc)        return pDst;    while(NUL != (*p1++ = *pSrc++));    return pDst;}/*  函数功能:合并字符串    参数表:pDst  = 目标字符串地址            pSrc  = 源字符串地址    返回值:指向目标字符串的指针*/char *strcat(char *pDst, const char *pSrc){    char *p1 = pDst;    if(NULL == pDst || NULL == pSrc)        return pDst;    while(NUL != *p1)        p1++;    while(NUL != (*p1++ = *pSrc++));    return pDst;}/*  函数功能:反转字符串    参数表:string = 字符串地址    返回值:指向字符串的指针*/char *strrev(char *string){    char ch, *p1, *p2;    // p1 指向 string 的头部    if(NULL == (p1 = p2 = string))        return NULL;    // p2 指向 string 的尾部    while(*p2)        ++p2;    p2--;    // 头尾交换反转    while(p2 > p1)    {        ch = *p1;        *p1++ = *p2;        *p2-- = ch;    }    return string;}/*  函数功能:将整数转换为字符串    参数表:value  = 欲转换的数据            string = 目标字符串的地址            radix  = 转换后的进制数    返回值:指向字符串的指针*/char *itoa(int value, char *string, int radix){    int i = 0, neg;    char ch;    if(NULL == string)        return NULL;    // 记录正负符号,并转为正数处理    if((neg = value) < 0)        value = -value;    // 从数字变为 ASCII 码    do    {        ch = value % radix;        if(ch < 10)            string[i++] = ch + '0';        else            string[i++] = ch - 10 + 'A';    } while((value /= radix) > 0);    // 正负符号    if(neg < 0)        string[i++] = '-';    // 字符串以 0 结尾。    string[i] = NUL;    // 反转(生成的时候是从个位开始的,是逆序的)    return(strrev(string));}/*  函数功能:将无符号整数转换为字符串    参数表:value  = 欲转换的数据            string = 目标字符串的地址            radix  = 转换后的进制数    返回值:指向字符串的指针*/char *utoa(unsigned value, char *string, int radix){    int i = 0, neg;    char ch;    if(NULL == string)        return NULL;    // 从数字变为 ASCII 码    do    {        ch = value % radix;        if(ch < 10)            string[i++] = ch + '0';        else            string[i++] = ch - 10 + 'A';    } while((value /= radix) > 0);    // 进制符    if(16 == radix)    {        string[i++] = 'x';        string[i++] = '0';    }    else if(8 == radix)    {        string[i++] = '0';    }    else if(2 == radix)    {        string[i++] = 'b';        string[i++] = '0';    }    // 字符串以 0 结尾。    string[i] = NUL;    // 反转(生成的时候是从个位开始的,是逆序的)    return(strrev(string));}

    stddef.h 这个文件就是定义了 NUL 和 NULL:

// 常量// —— 空指针 NULL#ifndef NULL    #define NULL    ((void *)0)#endif// —— 字符串结尾符 NUL#ifndef NUL    #define NUL     '\0'#endif

    kernel 里可以显示字符了,把几个参数显示出来先:

/*  kernel.c    内核    whoozit    2012-12-12*/#include "../lib/include/stddef.h"#include "../lib/include/string.h"#include "../kernel/include/PMode.h"#include "../kernel/include/graphics.h"#include "../kernel/include/io.h"// 全局变量结构typedef struct tag_Global_param{    unsigned int    dwMemorySize;    GRAPHICS_PARAM  tGraphics;} GLOBAL_PARAM;// 存放全局变量的物理地址(const.inc 中的 SEGMENTOFGPARAM * 0x10)#define PHYADDROFGPARAM     0x500// 存放点阵字库的物理地址(const.inc 中的 SEGMENTOFFONT * 0x10)#define PHYADDROFFONT       0x10000// GDT 表存放的物理内存地址(就接在全局变量后面吧)#define PHYADDROFGDT        (PHYADDROFGPARAM + sizeof(GLOBAL_PARAM))// 引用汇编指令函数extern void asm_hlt();void c_main(){    unsigned i, j;    unsigned short Screen_X, Screen_Y;    char string[80], number[33];    GLOBAL_PARAM g_Param;    // 初始化 GDT 表    InitGdt(PHYADDROFGDT);    // 取全局变量    memcpy((void *)&g_Param, (void *)(PHYADDROFGPARAM), sizeof(GLOBAL_PARAM));    // 初始化图形参数    InitGraphics(&(g_Param.tGraphics));    Screen_X = GetScreenX();    Screen_Y = GetScreenY();    // 画界面    SetColor(COLOR16_DEEPSKYBLUE);    rectangle(0,             0,             Screen_X - 1,  Screen_Y - 1);    SetColor(COLOR16_LIGHTGRAY);    rectangle(0,             Screen_Y - 28, Screen_X - 1,  Screen_Y - 28);    rectangle(0,             Screen_Y - 26, Screen_X - 1,  Screen_Y - 1);    SetColor(COLOR16_WHITE);    rectangle(0,             Screen_Y - 27, Screen_X - 1,  Screen_Y - 27);    rectangle(3,             Screen_Y - 24, 59,            Screen_Y - 24);    rectangle(2,             Screen_Y - 24, 2,             Screen_Y - 4);    rectangle(2,             Screen_Y - 3,  59,            Screen_Y - 3);    rectangle(60,            Screen_Y - 24, 60,            Screen_Y - 3);    rectangle(Screen_X - 47, Screen_Y - 3,  Screen_X - 4,  Screen_Y - 3);    rectangle(Screen_X - 3,  Screen_Y - 24, Screen_X - 3,  Screen_Y - 3);    SetColor(COLOR16_DARKGRAY);    rectangle(3,             Screen_Y - 4,  59,            Screen_Y - 4);    rectangle(59,            Screen_Y - 23, 59,            Screen_Y - 5);    rectangle(Screen_X - 47, Screen_Y - 24, Screen_X - 4,  Screen_Y - 24);    rectangle(Screen_X - 47, Screen_Y - 23, Screen_X - 47, Screen_Y - 4);    // 设置点阵字库    SetFont(PHYADDROFFONT, 8, 16);    SetColor(COLOR16_LIGHTVIOLET);    puts(10, Screen_Y - 20, "BEGIN");    SetColor(COLOR16_YELLOW);    putc(Screen_X - 40, Screen_Y - 20, 'O');    putc(Screen_X - 30, Screen_Y - 20, 'K');    // 显示变量    SetColor(COLOR16_BLACK);    strcpy(string, "Memory = ");    strcat(string, utoa(g_Param.dwMemorySize, number, 10));    puts(10, 10, string);    strcpy(string, "PhyAddrOfVideo = ");    strcat(string, utoa(g_Param.tGraphics.dwPhyAddrOfVideo, number, 16));    puts(10, 30, string);    strcpy(string, "Screen_X = ");    strcat(string, utoa(Screen_X, number, 10));    puts(10, 50, string);    strcpy(string, "Screen_Y = ");    strcat(string, utoa(Screen_Y, number, 10));    puts(10, 70, string);    strcpy(string, "BitsPerPixel = ");    strcat(string, utoa(g_Param.tGraphics.bBitsPerPixel, number, 10));    puts(10, 90, string);    while(1)        asm_hlt();}

    忙活了这么多天,总算看到字了,曙光啊,激动啊。。。。

182059_0pIT_580100.png

转载于:https://my.oschina.net/u/580100/blog/543200

你可能感兴趣的文章
搭建nginx+3*tomcat环境 实现session共享
查看>>
Phone状态监听
查看>>
MongoDB安装和基本运用
查看>>
python获取系统状态psutil模块
查看>>
软件分发、补丁推送排错
查看>>
如何把VHD转换成VHDX
查看>>
毕业只是开始:你准备好了吗?
查看>>
交互式自动化脚本模板
查看>>
顺丰和菜鸟对用户数据寸土不让 战争平息需监管层
查看>>
fatal error: libavutil/avconfig.h: No such file...
查看>>
spring集成activemq
查看>>
上网不掉钱
查看>>
我的友情链接
查看>>
Intruder reporting tool (for ssh remote login)
查看>>
创建cocopods库(swift版)
查看>>
linux启动不了,无法进入rescure模式,Mount: could not find filesystem '/dev/root
查看>>
TCP拥塞控制机制
查看>>
hdfs运维中遇到的问题记录
查看>>
手机屏幕适配
查看>>
软件测试LR通用性能分析流程
查看>>