那個點陣字庫數組這麼大,佔地方,難看。並且要換字體也不方便,還得從新制做。仍是直接把現有的字庫文件做爲一個資源文件比較好,loadre 到內存就行。c++
字庫暫時放到內存 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 0 iend ; ---------------------------------------------------------------------------------------- ; 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 : ; ---------------------------------------------------------------------------------------- ; GDTPtr GDTPtr dw Desc_End - Desc_Begin - 1 ; 界限 dd SEGMENTOFLOADER * 0x10 + Desc_Begin ; 基址 ; ---------------------------------------------------------------------------------------- ; 選擇子 SelectorCode equ Desc_Code - Desc_Begin SelectorData 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 裏,只是頭文件單列出來ide
/* 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:oop
// 常量 // —— 空指針 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(); }
忙活了這麼多天,總算看到字了,曙光啊,激動啊。。。。編碼