嵌入式操作系统课程作业之Write OS (转)

来源:互联网 发布:mysql分页高效 编辑:程序博客网 时间:2024/06/06 09:38

嵌入式操作系统课程作业之Write OS

姓名:唐良          学号: 024304xxxx

 

.     编译器的下载

1. Djgpp

Windows开发环境下,没有直接提供gcc编译器,所以需要从自己去下载WINDOWS版本的gcc编译器.Windows下有cygwin, devcpp, djgpp等工具都带有gcc编译器.但是djgpp最小,而且可以产生最单纯的binary代码,所以很多关于操作系统编写的网站上都推荐使用djgpp.

 

2. Nasm

Nasmmasm,以及as86等都很类似,都是支持16位和32位的汇编编译器.但是nasm使用起来比较轻活,能够产生多种中间代码格式,比如*.obj,*.o,所以很多操作系统编写的网站上也都推荐使用nasm作为汇编编译器.

 

. boot启动代码的编写

       Boot启动代码主要完成转载kernel,进入32为模式等工作.除开Linux标准代码外,网上关于boot启动的模板代码多不胜数,不过我使用的还是哈工大的pyos的启动代码.

       Boot.s的代码如下:

 

[BITS 16]

[ORG 0x7C00]

       jmp  main

; ----------------------------------------------------------------------------------------------

; 数据定义

bootdrive db    0

; ----------------------------------------------------------------------------------------------

; GDT 定义

gdt:

       gdt_null:

              dd    0

              dd    0            ; 空描述符全是0

 

       gdt_code_addr equ $ - gdt     ; 数据段在GDT表中的位置

       gdt_code:

              dw   0xffff             ; 段大小为4GB

              dw   0            ; 基址的低16

              db    0            ; 基址的高八位

              db    10011010b     

              db    11001111b

              db    0

 

       gdt_data_addr equ $ - gdt      ; 数据段在GDT表中的位置

       gdt_data:

              dw   0xffff

              dw   0x0000

              db    0

              db    10010010b

              db    11001111b

              db    0

      

       gdt_end:

       gdt_addr:

              dw   gdt_end - gdt - 1    ; GDT 表的大小

              dd    gdt                 ; GDT 表的位置

; --------------------------------------------------------------------------------------

main:

       mov [bootdrive] , dl       ; 他得到启动的驱动器号

       xor ax , ax             ; 设置 DS

       mov ds , ax

 

       ; 清屏

       ;mov ax , 3            ; 设置清屏功能号

       ;int 0x10         ; 调用 BIOS 10 号中断清屏

 

       .ResetFloppy          ; 重置磁盘

       mov ax , 0             ; 设置重置磁盘的功能号

       mov dl , [bootdrive]       ; 选择启动磁盘

       int 0x13

       jc .ResetFloppy             ; 如果出错则重试

 

       .ReadFloppy          ; 读内核到内存中 0000:9000 (es:bx)

       xor ax , ax             ; 设置 es 寄存器

       mov es , ax

       mov bx , 0x9000

       mov ah , 2             ; 设置读磁盘功能号

       mov dl , [bootdrive]       ; 设置欲读驱动器号

       mov ch , 0             ; 磁头号

       mov cl , 2              ; 起始扇区号

       mov al , 17            ; 读入扇区数量   

       int 13h          

       jc .ReadFloppy

      

       mov dl , [bootdrive]              ; 停止驱动器

       mov edx , 0x3f2

       mov al , 0x0c

       out dx , al

 

       cli                         ; 关中断

        lgdt [gdt_addr]                      ; 载入 GDT 的描述符                                      

        mov eax , cr0               ; 下面三句设置 cr0 的第 0 位(PE位)为1,表示进入保护模式

        or eax , 1                                                                       

        mov cr0 , eax   

      

        jmp gdt_code_addr:code_32  ; 跳入32位的代码段中

 

[BITS 32]

code_32:

       mov ax , gdt_data_addr  ; 以下三句设置 DSESSSFSGS的置为数据段描述表的位置

       mov ds , ax

       mov es , ax

       mov ss , ax

       mov fs , ax

       mov gs , ax

 

       mov esp , 0xffff            ; 设置堆栈的头指针   

              

       jmp gdt_code_addr:0x9000    ; 跳入内核

;---------------------------------------------------------------------------

times 510-($-$$) db 0

db 0x55

db 0xAA

 

. 编译boot启动代码

       nasm十分简单. 可以很容易生成bin文件.它默认生成的也是bin原始代码.直接输入nasmw boot.s就能够得到boot原始代码.

       然后将通过WinHexboot的全部代码复制到一张1.44MB的软盘镜像文件的头512的字节中去.可以通过Bochs,Virtual PC,VMWare来建立软件镜像文件.这些软件的软盘镜像文件都是原始数据文件,没有任何关于软盘的配置数据,所以直接通过WinHex中的Ctrl+CCtrl+B(千万不能是Ctrl+V)就可以完成复制了.

 

. 编写显示内核进入装载的C代码

       如果按照pyos的第二个实验来做,我得到的C语言生成的代码是.data数据段放在了.text代码段前面,就不能直接一下jmp 0x9000进入kernel的初始程序的代码段.后来我参考了网上一些做法,有种办法是编写link.script的连接脚本,有些是增加一个类似crt0.sC语言启动汇编.我选择的是后者.

1. 编写C代码

char* msg = "Welcome to SCU Operation System!Version 0.0001 by tangl_99" ;

void k_main()

{

       unsigned char* videomem = ( unsigned char* )0xb8000 ;

       while( *msg != '/0' ){

              *videomem++ = *msg++ ;

              *videomem++ = 0x1b ; 

       }

       for(;;);

}

这里使用k_main作为入口函数,有别于通常的main入口函数.

 

2. 编写crt0.s启动代码

[BITS 32]

[global start]

[extern _k_main] ; this is in the c file

 

start:

  call _k_main

 

  cli  ; stop interrupts

  hlt ; halt the CPU

 

3. 编译连接kernel初始程序

       编译连接部分我就没有参照pyos的做法了.根据网络的通常的做法,我的编译连接命令如下:

setdjgpp d:/djgpp d:/djgpp                  # djgpp需要预先设置一下

gcc –c kernel.c

nasmw –f aout crt0.s

ld -nostartfiles --oformat binary -Ttext 0x9000 -o kernel crt0.o kernel.o

最后会生成1024字节大小的 kernel原始代码文件.还是通过WinHex将其复制到软盘镜像文件,要从第512个字节位置开始复制.

 

. Virtual PC下启动运行生成OS 软盘镜像文件

       Virtual PC的使用就不再多说了,Virtual PC应该是Windows下最容易使用的模拟器.

下面是运行0.0001版本的截图:

 

 

 
原创粉丝点击