操作系统的完整代码——镜像构建代码ycos.cpp

    为了介绍如何用YC编译器开发操作系统,作者设计并实现了一个简单的操作系统:YCOS。下面对YCOS源码进行详细分析和解释。

1. YCOS镜像构建代码ycos.cpp
#include "ycos.h"
#define L(_String) L ## _String
#define yc_assert(EP) ((EP)?((void)(_wassert(L###EP,L(__FILE__),__LINE__),0)):0)

void main()
{
    char *boot_buf,*head_buf,*ker_buf,*fs_buf,*mm_buf;
    int boot_len = YC_cppCompile(&boot_buf,"ycboot.cpp");     //编译引导代码
    int head_len = YC_cppCompile(&head_buf,"ychead.cpp");     //编译初始化代码
    int ker_len = YC_cppCompile(&ker_buf,"ycker.cpp");        //编译内核代码
    create_exp();                                       //编译驱动和应用程序
    int fs_len = YC_cppCompile(&fs_buf,"ycfs.cpp");     //编译文件管理代码
    int mm_len = YC_cppCompile(&mm_buf,"ycmm.cpp");     //编译内存管理代码

    yc_assert(!boot_len);                  //引导代码语法错误检查
    yc_assert(boot_len > ycboot_SIZE);     //引导代码长度错误检查
    yc_assert(!head_len);                  //初始化代码语法错误检查
    yc_assert(head_len > ychead_SIZE);     //初始化代码长度错误检查
    yc_assert(!ker_len);                   //内核代码语法错误检查
    yc_assert(!fs_len);                    //文件管理代码语法错误检查
    yc_assert(!mm_len);                    //内存管理代码语法错误检查
    yc_assert(ycker_SIZE < ychead_SIZE + ker_len + fs_len + mm_len);
    yc_assert(ycker_SIZE < ((YCEXE*)ker_buf)->codelen+((YCEXE*)fs_buf)->codelen+
                                                     ((YCEXE*)mm_buf)->codelen);

    byte *imgBuf = new byte[DISK_SIZE];  //把上述执行代码按指定位置写入镜像文件
    memcpy(imgBuf, boot_buf, boot_len);    //引导代码
    memcpy(&imgBuf[ycboot_SIZE + ycker_SIZE - ychead_SIZE], head_buf, head_len);
    memcpy(&imgBuf[ycboot_SIZE], ker_buf, ker_len);   //内核代码
    memcpy((char*)&imgBuf[ycboot_SIZE + ker_len], fs_buf, fs_len);//文件管理代码
    memcpy((char*)&imgBuf[ycboot_SIZE + ker_len + fs_len], mm_buf, mm_len);
    YC_writefile("ycos.img",imgBuf,DISK_SIZE);  //将 imgBuf 写入镜象文件

    free(boot_buf);
    free(ker_buf);
    free(head_buf);
    free(fs_buf);
    free(mm_buf);
    delete imgBuf;

    #define bochs_src `megs: 128
                       romimage: file=BIOS-bochs-latest
                       vgaromimage: file=VGABIOS-lgpl-latest
                       ata0-master: path=ycos.img, type=disk
                       boot: c
                       log: bochs.out`

    YC_writefile("ycos.src", bochs_src, sizeof bochs_src);
    YC_cppRun("bochs.exe -q -f ycos.src",-1);   //执行bochs.exe计算机模拟器
}

void create_exp()
{
    auto compiler_exp = [](char *fileptr,char *extptr)
      {
         char file_buf[256];
         strcpy(file_buf,fileptr);
         strcpy(&file_buf[strrchr(fileptr,'.') - fileptr], extptr);
         remove(file_buf);
         char *srcbuf;
         int glen = YC_cppCompile(&srcbuf,fileptr);     //调用编译函数
         YC_writefile(file_buf,srcbuf,glen);
         free(srcbuf);
         return glen;
      };
    yc_assert(!compiler_exp("yctty.cpp", ".sys")); //将yctty.cpp编译到yctty.sys
    yc_assert(!compiler_exp("ycshell.cpp", ".exp")); //编译到ycshell.sys文件
    yc_assert(!compiler_exp("pro0.cpp", ".exp")); //将pro0.cppp编译到pro0.exp
    yc_assert(!compiler_exp("pro1.cpp", ".exp")); //将pro1.cppp编译到pro1.exp
    yc_assert(!compiler_exp("pro2.cpp", ".exp")); //将pro2.cppp编译到pro2.exp
    yc_assert(!compiler_exp("pi2.cpp", ".exp"));  //将pi2.cppp编译到pi2.exp文件
    yc_assert(!compiler_exp("exp0.cpp", ".exp")); //将exp0.cppp编译到exp0.exp
    yc_assert(!compiler_exp("drv.cpp", ".sys"));  //将drv.cppp编译到drv.sys文件
    yc_assert(!compiler_exp("dra.cpp", ".exp"));  //将dra.cppp编译到dra.exp文件
    yc_assert(!compiler_exp("drb.cpp", ".exp"));  //将drb.cppp编译到drb.exp文件
    yc_assert(!compiler_exp("ex0.cpp", ".exp"));  //将ex0.cppp编译到ex0.exp文件
}

                      c/c++代码文件: ycos.cpp

编译:在cmd状态上键入YC命令:ycc ycos.cpp
      或在YC编辑器中调入ycos.cpp, 按F6键
      生成ycos.exe
执行:在命令行上键入ycos,
      或在YC编辑器中调入ycos.cpp, 按F7键
      将显示一个对话框。
      在对话框中选择“Continue”项,按回车键便进入YCOS的界面。

源代码分析
    YC_cppCompile()函数编译YCOS的所有文件
    yc_assert()函数检查生成的代码长度是否与ycos.h中设置的值是否相符
    语句byte *imgBuf = new byte[DISK_SIZE]申请大小为DISK_SIZE的内存
    memcpy()函数将YC_cppCompile()生成的执行代码拷入imgBuf的适当位置
    语句YC_writefile(“ycos.img”,imgBuf,DISK_SIZE)将imgBuf写入镜像文件ycos.img
    语句#define bochs_src …和 YC_writefile(“ycos.src”,…) 生成设置文件ycos.src
    语句YC_cppRun(“bochs.exe -q -f ycos.src”)执行计算机模拟器软件bochs启动YCOS

    auto compiler_exp = [](char *fileptr,char *extptr){…}定义了一个局部的lambda函数,如果把它定义为全局函数,则应该按如下方式定义:
    void compiler_exp(char *fileptr,char *extptr){…}
    compiler_exp()函数生成键盘驱动程序yctty.sys、命令处理程序ycshell.sys和一些示例代码。

2. 头文件ycos.h
#define DATA_POS     0x90000
#define ycboot_SIZE  (512 * 2)        //ycboot.cpp的最大长度
#define ychead_SIZE  0x2000           //ychead.cpp的最大长度
#define ycker_SIZE   (1024 * 64 * 4)  //ycker ycfs ycmm ychead代码之和的最大长度
#define ycker_POS    (DATA_POS - ycker_SIZE)  //ycker.cpp 的调入位置

#define e820_POS     380
#define KERNEL_POS   0xC0000000   //内核映射地址
#define KERNEL_CS    8 * 1        //代码选择子
#define KERNEL_DS    8 * 2        //数据选择子
#define PAGE_SIZE    4096                    //页大小
#define PAGE_MASK    (~(PAGE_SIZE-1))
#define DIR_SIZE     (PAGE_SIZE * 1024)      //页目录大小
#define DISK_SIZE    (1024 * 1024 * 2)       //硬盘大小

static_assert((ycboot_SIZE % 512) == 0, "ycboot_SIZE Error!");
static_assert((ycker_SIZE % (1024 * 64)) == 0, "ycker_SIZE Error!");
static_assert((DATA_POS % (1024 * 64)) == 0, "DATA_POS Error!");
static_assert((KERNEL_POS % DIR_SIZE) == 0, "KERNEL_POS Error!");

typedef unsigned char byte;
#define to_memPtr(pLink)     ((byte*)pLink + sizeof(YMEM))
#define to_memLink(_Memory)  (YMEM*)((byte*)_Memory - sizeof(YMEM))
#ifndef offsetof
#define offsetof(s,m)  (unsigned int)&(((s*)0)->m)
#endif

struct YMEM    //内存链表结构
{
        YMEM  *pNext;
        YMEM  *pLast;
        unsigned int size;
        union
          {
            unsigned int addr;
            int   flag;
          };
};
#define freeMemLINK_POS  0x100000     //空闲物理内存链表的内存位置
#define freeMemLink_NUM  (1024*16)    //空闲物理内存链表的最大项数
#define PageDir_POS   (freeMemLINK_POS + sizeof(YMEM) * freeMemLink_NUM) //页目录
#define PageTable_pos (PageDir_POS + 0x1000)  //页表内存位置
static_assert((PageDir_POS % PAGE_SIZE) == 0, "PageDir_POS Error!");

enum  //定义按键值
{
    VK_BACK = 0x08, VK_TAB,
    VK_CLEAR = 0x0C, VK_RETURN,
    VK_PAUSE = 0x13, VK_CAPITAL,
    VK_ESCAPE = 0x1B,
    VK_PRIOR = 0x21,VK_NEXT,VK_END,VK_HOME,VK_LEFT,VK_UP,VK_RIGHT,VK_DOWN,
    VK_PRINT = 0x2A,
    VK_INSERT = 0x2D, VK_DELETE,
    VK_F1 = 0x70,VK_F2,VK_F3,VK_F4,VK_F5,VK_F6,VK_F7,VK_F8,VK_F9,VK_F10,VK_F11,
    VK_F12,
    VK_MULTIPLY = 0x6A, VK_ADD,
    VK_SUBTRACT = 0x6D,
    VK_NUMLOCK = 0x90, VK_SCROLL,
    VK_LSHIFT = 0xA0, VK_RSHIFT, VK_LCONTROL, VK_RCONTROL, VK_LMENU, VK_RMENU,
};

#pragma pack(1)
struct GDT_PTR    //全局描述符结构
{
        unsigned short size;
        char *addr;
};
struct e820map   //内存信息结构
{
    int nr_map;
    struct e820entry
      {
        unsigned long long addr;
        unsigned long long size;
        unsigned long type;
      } map[32];
};
static_assert(e820_POS + sizeof e820map <= ycboot_SIZE, "e820_POS Error!");
#pragma pack()

struct YDescriptor  //段描述符结构
{
        unsigned short  limit_low;
        unsigned short  base_low;
        byte     base_mid;
        byte     attr1;
        byte     limit_high_attr2;
        byte     base_high;
};

struct YProcess   //进程数据结构
{
        unsigned int    gs;
        unsigned int    fs;
        unsigned int    es;
        unsigned int    ds;

        unsigned int    edi;
        unsigned int    esi;
        unsigned int    ebp;
        unsigned int    kernel_esp;
        unsigned int    ebx;
        unsigned int    edx;
        unsigned int    ecx;
        unsigned int    eax;

        unsigned int    eip;
        unsigned int    cs;
        unsigned int    eflags;
        unsigned int    esp;
        unsigned int    ss;

        unsigned short  ldt_sel;
        YDescriptor     ldts[2];     //局部段描述符
        int             m_ticks;
        int             priority;
        unsigned int    pid;
        YMEM            *pHead;
        char            *CommandLine;
};

struct YTSS   //保存堆栈指针的结构
{
        unsigned int    backlink;
        unsigned int    esp0;
        unsigned int    ss0;
        unsigned int    $[25];
};

struct YCEXE  //执行文件头部结构
{
        char  name[32];
        int   srcpos;
        int   srclen;
        int   org;
        int   bit;
        int   segnum;
        int   funpos;
        int   codelen;
        int   addrnum;
        int   addrpos;
        int   argpos;

        int   innernum;
        int   innerpos;
        int   ldpos;
        int   verpos;
        int   exitpos;
        int   retsize;
        char  doswinpos;
        char  compress;
        char  testflag;
        char  vmflag;
        int   headfilepos;
        int   headfilelen;
        int   autofilelen;

        int   stacksize;
        int   length;
};

struct BINPOS
{
        int  pos;
        int  len;
};

struct ycfsCLASS  //文件管理接口
{
        virtual byte *stdcall get_file_code(char *fptr,int flen=0,int *pSize=0);
        virtual char *stdcall get_file_name(int pos,int &size);
};

struct ycmmCLASS  //内存管理接口
{
    virtual YMEM *stdcall malloc(YMEM *pHead,unsigned int _Size,int isHigh=0);
    virtual YMEM *stdcall realloc(YMEM *oldLink,unsigned int _NewSize);
    virtual void stdcall free(YMEM *pLink);
    virtual YMEM *stdcall get_head();
};

struct ycttyCLASS  //显示和键盘管理接口
{
    virtual void stdcall keyboard_proc();
    virtual void stdcall sys_write(int *pdata);
    virtual void stdcall wr_prompt();
    virtual void stdcall clear_screen(int bpos,int len);
    virtual void stdcall cls();
    virtual void stdcall pmt_cursor_pos(int cpos);
    virtual void stdcall set_disk(int mval);
    virtual void stdcall display_LED(byte capsV,byte numV,byte scrollV);
    virtual void stdcall sys_cursor(int curpos);
    virtual void stdcall keyboard_read(int &vk_char,int &vk_value,int &vk_press,
                                        byte &capsL,byte &numL,byte &scrollL,
                                        byte &shiftV,byte &altV,byte &ctrlV);
};

                        YCOS头文件: ycos.h

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值