十8、能夠輸出文字了

    那個點陣字庫數組這麼大,佔地方,難看。並且要換字體也不方便,還得從新制做。仍是直接把現有的字庫文件做爲一個資源文件比較好,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();
}

    忙活了這麼多天,總算看到字了,曙光啊,激動啊。。。。編碼

相關文章
相關標籤/搜索