赞
踩
4 C与汇编
我们都知道一个系统要么是32位,要么是64位的。没错,不然这个系统就太大了。但是,我们不可能分开编写两个操作系统,所以,我们要使用宏来区分开32位和64位。
这个已经和我们的操作系统开发没有关系了,所以读者可以自行在chapter4/a中看源代码。
接下来的任务就是加载内核了。我们之前写过一个DiskRead函数,所以我们可以利用一下这个函数。我们在进入保护模式之前(为了使用BIOS)把KERNEL(还不存在)读入内核:
#78 call DiskReset ; Reset Device 0
#79
#80 mov ax,KERNELFILE_SEGMENT ; Target Address for INT 13h
#81 mov es, ax ;Argument for DiskRead::ES
#82
#83 mov ax, KERNEL_FILE_LBA ;Argument for DiskRead::LBA Address
#84 mov cl,KERNEL_SIZE_SECT ; Argument for DiskRead::Size
#85
#86 mov bx, KERNELFILE_OFFSET ;Argument for DiskRead::BX
#87 call DiskRead
代码 4.1.1 读入内核(chapter4/a/boot/loader.asm)
不多说,这些宏都被定义在loader.inc里面。
我们然后进入保护模式,用memcpy把内核拷贝至0x100000的位置。这些都很简单,我也就不多说了,看代码即可。接下来我们得弄一个内核出来。内核应该是32位的了,所以我们可以使用C语言。当然,在那之前,我们先用汇编将控制权交给C。
这段代码写起来非常容易。完全没有技术含量。
%include "boot/include/loader.inc"
[section .text] ; 代码在此
global _start ; 导出 _start
extern cstart
_start:
call cstart
cli
hlt
代码 4.1.2 战斗力只有5的代码(chapter4/a/kernel/entry.asm)
重头戏在start.c里面。目前的start.c只提供了一个显示文字的功能。
char* dispPos=(char*)0xB8000;
void puts(char* str){
unsigned charc;
while((c=*(str++))!=0){
if(c==13){
dispPos-=((unsigned int)dispPos)%160-64;
/* Notice: "-64" because 0xB8000 % 160 = 64 */
}else if(c==10){
dispPos+=160;
}else{
*(dispPos++)=c;
*(dispPos++)=0x0F;
}
}
}
void cstart(){
puts("\nKernel is ready!");
}
代码 4.1.3 渣渣(chapter4/a/kernel/start.c)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。