(二)手写操作系统-32位保护模式导入C语言

         首先,非常感谢《30天自制操作系统》这本书,为我解决了非常多的困惑并提供了一些工具的源码,以便于我用来修改并兼容中文汇编。

         因此这篇文章用中文汇编的方式展示书上32位保护模式和C语言的导入(后面开发可能不这样写)。下面直接贴上源码:        

柱面数  等  10

    装载 0x7c00

    跳      主体

    字      0x90

    字      "NAJCNAJC"

    双字 512

    字      1

    双字 1

    字      2

    双字 224    

    双字 2880

    字      0xf0

    双字 9

    双字 18

    双字 2

    四字 0

    四字 2880

    字      0,0,0x29

    四字 0xffffffff

    字      "JC-OS--NAJC"

    字      "FAT12   "

    补字 18

主体:

    移      寄加,0 

    移      段堆,寄加

    移      栈指,0x7c00

    移      段数,寄加

    移      寄加,0x0820

    移      段附,寄加

    移      寄计高,0

    移      寄数高,0

    移      寄计低,2

循环读:

    移      变源,0

重试:

    移      寄加高,0x02

    移      寄加低,1

    移      寄基,0

    移      寄数低,0

    中断 0x13

    不错跳  下一遍

    加      变源,1

    比      变源,5

    高等跳  错误

    移      寄加高,0

    移      寄数低,0

    中断 0x13

    跳      重试

下一遍:

    移      寄加,段附

    加      寄加,0x0020

    移      段附,寄加

    加      寄计低,1

    比      寄计低,18

    低等跳  循环读

    移      寄计低,1

    加      寄数高,1

    比      寄数高,2

    低跳 循环读

    移      寄数高,0

    加      寄计高,1

    比      寄计高,柱面数

    低跳 循环读

    移      [0x0ff0],寄计高

    跳      0xc200

错误:

    移      变源,消息

循环输出:

    移      寄加低,[变源]

    加      变源,1

    比      寄加低,0

    等跳 最后

    移      寄加高,0x0e

    移      寄基,15

    中断 0x10

    跳      循环输出

最后:

    休

    跳      最后

消息:

    字      0x0a, 0x0a

    字      "load error"

    字      0x0a

    字      0

    补字 0x1fe-($-$$)

    字      0x55, 0xaa

上面是系统的启动引导,该引导写入在磁盘的第0柱面第0号磁头第1扇区。启动时把该引导装载到0x7c00。引导的源码实现了从第0柱面第0号磁头第2扇区读取软盘的10个柱面一共180KB写入到内存0x8200地址(段附x16+寄基)。写入完成后跳转到0xc200(下面系统文件在0x4200,而上面读取从0x200开始,因此0x8200+0x4200-0x200=0xc200)进行执行。

接下来就是加载到0xc200处的系统源码:

BOTPAK  等  0x00280000

DSKCAC  等  0x00100000

DSKCAC0 等  0x00008000

启动区  等  0x0ff0

键盘灯  等  0x0ff1

模式 等  0x0ff2

宽      等  0x0ff4

高      等  0x0ff6

缓冲区  等  0x0ff8

    装载 0xc200

    移      寄加低,0x13

    移      寄加高,0x00

    中断 0x10   

    移      转字 [模式],8

    移      转双字  [宽],320

    移      转双字  [高],200

    移      转四字  [缓冲区],0x000a0000

    移      寄加高,0x02

    中断 0x16

    移      [键盘灯],寄加低



    移      寄加低,0xff

    出      0x21,寄加低

    空

    出      0xa1,寄加低

    禁中断



    调      waitkbdout

    移      寄加低,0xd1

    出      0x64,寄加低

    调      waitkbdout

    移      寄加低,0xdf

    出      0x60,寄加低

    调      waitkbdout



    全描 [GDTR0]

    移      高寄加,寄控0

    和      高寄加,0x7fffffff

    或      高寄加,0x00000001

    移      寄控0,高寄加

    跳      pipelineflush

pipelineflush:

    移      寄加,8

    移      段数,寄加

    移      段附,寄加

    移      段附f,寄加

    移      段附g,寄加

    移      段堆,寄加



    移      高变源,bootpack

    移      高变目,BOTPAK

    移      高寄计,512*1024/4

    调      memcpy



    移      高变源,0x7c00

    移      高变目,DSKCAC

    移      高寄计,512/4

    调      memcpy



    移      高变源,DSKCAC0+512

    移      高变目,DSKCAC+512

    移      高寄计,0

    移      寄计低,转字  [启动区]

    符乘 高寄计,512*18*2/4

    减      高寄计,512/4

    调      memcpy



    移      高寄基,BOTPAK

    移      高寄计,[高寄基+16]

    加      高寄计,3

    逻右移  高寄计,2

    零跳 skip

    移      高变源,[高寄基+20]

    加      高变源,高寄基

    移      高变目,[高寄基+12]

    调      memcpy

skip:

    移      高栈指,[高寄基+12]

    跳      转四字  2*8:0x0000001b

waitkbdout:

    入      寄加低,0x64

    和      寄加低,0x02

    非零跳  waitkbdout

    返

memcpy:

    移      高寄加,[高变源]

    加      高变源,4

    移      [高变目],高寄加

    加      高变目,4

    减      高寄计,1

    非零跳  memcpy

    返

    section align=16

GDT0:

    补字 8

    双字 0xffff,0x0000,0x9200,0x00cf

    双字 0xffff,0x0000,0x9a28,0x0047

    双字 0

GDTR0:

    双字 8*3-1

    四字 GDT0

    section align=16

bootpack:

 

以上代码是进入32位保护模式的代码,这些先不做介绍,“移      高变源,bootpack

          高变目,BOTPAK

          高寄计,512*1024/4

          memcpy”这段代码是把bootpack以下的部分复制到0x00280000,由于每次复制4个字节所以除于4。最后跳转到0x28001b开始执行下面代码

void io_hlt();

void write_mem8(int addr, int data);

void JCMain()

{

    int i;

    char *p;

    p = 0xa0000;

    for (i = 0;i<=0xffff;i++)

    {

        p[i] = i &0x0f;

    }

    for(;;)

    {

        io_hlt();

    }

}

通过编译并通过gas2najc.exe转码后:

[BITS 32]

    EXTERN  _io_hlt

[SECTION .text]

    全局 _JCMain

_JCMain:

    入栈 高基指

    异或 高寄数,高寄数

    移  高基指,高栈指

L6:

    移  寄加低,寄数低

    和  高寄加,15

    移  转字 [655360+高寄数],寄加低

    自增 高寄数

    比  高寄数,65535

    小等跳  L6

L7:

    调  _io_hlt

    跳  L7

可以看出C语言的函数在汇编里面是标签,我们这里定义了全局的_JCMain,经过最终链接后会变成地址。JCMain是我们的main函数,启动时调用。Main里面就是对0xa000到0xffff进行赋值,通过makefile生成img格式,可以在vmware虚拟机加载,结果显示条纹。

后续有时间时,我会按照linux启动的模式用中文汇编再次写一个系统加载。

CSDN源码:https://download.csdn.net/download/u011736517/12142310

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值