操作系统的完整代码——引导代码ycboot.cpp

引导代码ycboot.cpp
#define YCORG  0
#define YCBIT  16
#include "ycos.h"

asm void print();
asm void read_sector();
#define setup_POS    (ycboot_SIZE - 512)

asm void main()
{
            xor     ax,ax //加电时, BIOS执行: memcpy(0000:7c00h, &imgBuf[0], 512)
            mov     ds,ax
            mov     ax,DATA_POS / 16
            mov     es,ax

            //memcpy(9000:0000h, &imgBuf[0], 512)
            mov     ecx,512 / 4
            mov     esi,7c00h
            xor     edi,edi
            rep     movsd
            jmp     DATA_POS / 16 : rd_boot  //该语句使cs由0000h变为9000h

  rd_boot:  mov     ax, cs       //此时 cs = 9000h
            mov     ds, ax
            mov     es, ax
            mov     ss, ax
            mov     sp, 0xfff0   //设置堆栈为9000:fff0, 用于push call ret等语句

            //清屏
            mov     dx, 1f4fh
            mov     bx, 0f10h
            mov     ax, 0600h
            int     10h

            //显示 Loading 信息
            mov     al, 0
            mov     bx, 0x0047
            call    print

            //memcpy(9000:setup_POS, &imgBuf[setup_POS], ycboot_SIZE - setup_POS)
            mov     eax,setup_POS/512
            mov     edx, 0
            mov     di, cs
            mov     bx, setup_POS
            mov     cx, (ycboot_SIZE - setup_POS) / 512
            call    read_sector

            //显示[setup_POS]处的字符
            mov     ax,0xb800
            mov     gs,ax
            mov     al, [setup_POS]
            mov     byte gs:[(80*0 + 78)*2 + 0], al
            mov     byte gs:[(80*0 + 78)*2 + 1], 0xcf

            //判断是否读入了ycboot的setup_main()函数
            cmp     byte [setup_POS], 66h
            jz      mn_0
            mov     al, 1
            mov     bx, 0x0017
            call    print     //ycboot未被读入, 显示错误信息

     mn_0:  jmp     setup_POS  //跳到&imgBuf[setup_POS]代码处的setup_main()函数
}

asm char msg1()
{
    db   "YCos is booting... - ycboot.cpp"
    db   "Reading Error! - ycboot.cpp    "
}
asm void print()
{
            mov     dh, al        //显示位置(dl,dh)
            mov     dl, 0
            mov     cx, 31        //字符串msg1的长度
            mul     cl
            mov     bp, msg1      //字符串msg1的地址
            add     bp, ax
            mov     ax, 1301h     //显示功能号
            int     0x10          //显示字符串
            ret
}

asm void hd_pack()  {  db  16, 15 dup(0)  }
asm void read_sector()
{
            push    eax
            push    edx
            push    si
            mov     si, hd_pack
            mov     [si + 2], cx    //read cx sectors into buffer
            mov     [si + 4], bx    //buffer offset
            mov     [si + 6], di    //buffer segment
            mov     [si + 8], eax   //dada sector pos low
            mov     [si + 12], edx  //dada sector pos high
            mov     ah, 42h         //read mode
            mov     dl, 80h         //disk C
            int     0x13
            pop     si
            pop     edx
            pop     eax
            ret
}

#org(e820_POS)    //内存信息的存放位置
asm void $() { db 0 }
#org(510)
asm void flag() { dw 0xaa55 }

int64 Ygdt[] = {0, 0x00cf9a000000ffff, 0x00cf92000000ffff};
GDT_PTR  gdt_descr = { sizeof Ygdt, (char*)Ygdt + DATA_POS  };

#org(setup_POS)
asm void setup_main()
{
            //memcpy(1000:5000h, &imgBuf[ycboot_SIZE], ycker_SIZE)
            mov     eax, ycboot_SIZE / 512  //逻辑扇区 = edx*100000000h + eax
            mov     edx, 0
            mov     di, ycker_POS / 16   //数据被读到 di:bx
            mov     bx, 0       //每次最多读 10000h = 64k 字节数据 = 128个扇区
            mov     cx, 128     //读128个扇区 = 128 * 512 = 10000h
   rf_000:  call    read_sector
            add     eax, 128    //调整磁盘逻辑扇区, 以备下次读取数据
            adc     edx, 0
            add     di, 1000h   //调整缓冲区位置
            cmp     di, DATA_POS / 16  //检查数据是否被读完
            jne     rf_000      //数据未被读完, 再读一次

            //将系统内存信息读到9000:[e820_POS]
            xor     ebx,ebx
            mov     [e820_POS],ebx
            mov     di, e820_POS + offsetof(e820map,map)
    sm_00:  mov     eax, 0000e820h
            mov     ecx, 20
            mov     edx, 'SMAP'
            int     15h
            jc      sm_01
            cmp     eax, 'SMAP'
            jne     sm_01
            mov     eax,[e820_POS]
            cmp     dword [e820_POS],32
            jnl     sm_01
            inc     dword [e820_POS]
            add     di, 20
            cmp     ebx, 0
            jne     sm_00

    sm_01:  lgdt    cs:gdt_descr  //装入全局段描述符
            mov     al,0xdf
            out     0x60,al       //打开A20
            mov     ax,0x0001
            lmsw    ax            //进入保护模式
            jmp     dword KERNEL_CS : DATA_POS - ychead_SIZE  //跳入 ychead.cpp
}

                      C/C++代码文件: ycboot.cpp

源代码分析
    语句#define YCORG 0 定义生成代码的位置,定义它后不再使用默认的头文件
    语句#define YCBIT 16 定义生成16位不带头部信息的执行代码。
    asm void main()为程序入口函数
    代码mov ecx,512 / 4; mov esi,7c00h; xor edi,edi; rep movsd将引导扇区中的512字节考到内存9000:0000处,相当于执行C代码: memcpy(0x90000,&imgBuf[0],512)。
    语句 #org(510)使函数asm void flag() { dw 0xaa55 }处于第510字节的位置
    语句:…
    mov cx, (ycboot_SIZE - setup_POS) / 512
    call read_sector
    将ycboot.cpp的第512字节后的代码拷到内存9000:0200处
    语句jmp setup_POS使程序跳到9000:0200(即asm void setup_main()函数)处
    语句:
    mov cx, 128 //读128个扇区 = 128 * 512 = 10000h
    call read_sector
    将ycker.cpp,ychead.cpp,ycfs.cpp,ycmm.cpp执行代码拷贝到内存ycker_POS(即1000:5000)处,相当于执行C语句memcpy(0x50000,&imgBuf[ycboot_SIZE],ycker_SIZE)
    语句jmp dword KERNEL_CS : DATA_POS - ychead_SIZE使程序跳到0x90000-0x2000处,分析ycos.cpp语句
    memcpy(&imgBuf[ycboot_SIZE + ycker_SIZE - ychead_SIZE],head_buf,head_len)可知,此处是ychead.cpp代码,故程序便进入ychead.cpp的main()函数。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值