您的位置:首页 > 其它

所需的基础知识

2011-12-13 09:27 246 查看
这里是我需要写的 《操作系统原理及实践》的草稿,只是一个框架,会有一些省略的地方,比如图表,文字也是一些大纲性质的,并没做很细致的说明,但是代码是可以保证的,代码分析相对简单,为什么这么做的说明也是一个提示性的文字,这些会在后面进行补充。如果有心学,并没有太大的困难。

===============================================================================================================

这里,我将通过一个小型的操作系统来讲解操作系统原理,这个操作系统我把他命名为Lenix,因为这个系统是学习用的,所以用了Learn这个词,然后随大流的用了ix后缀,就有了Lenix这个名字,也就是学习用的os。呵呵,我有两个操作系统了,一个SHEMOX,一个lenix。

因为是学习用的,所以我就避开了一些很重要,但实际上不属于操作系统核心的内容,比如保护模式、系统引导。这两项内容,让很多想动手的人望而却步。当然,这也有很大一部分原因是目前流传的资料误导而造成的。这些所谓的操作系统编写教程或者书籍,一开篇就讲这两样,而且还是用汇编来写的代码,写的人也许懂,但可以保证,单单看这些资料,肯定看不懂,还得去找相应的保护模式的资料,学了一遍,在会过头来学操作系统。通常情况就是学会保护模式了,能引导机器了,就以为自己能写操作系统了。但实际上到了这一步,连OS的边都没摸着。废话不多说了。

Lenix使用BC3.1,在DOS下开发。BC31可以编译汇编文件,这就不必使用多种开发工具了。当然,这也会受到一定的限制,就是一些286以后的指令不能使用,比如pusha,还有就是寄存器的使用会受到限制,现在的汇编中,可以使用任何一个寄存器作为基址寄存器,可以写 mov ebx,[eax + 8]这样的程序,但是在BC31中,只能用bx、bp来做基址寄存器,也就是必须写为 mov ax,[bx + 2],注意16位和32位的区别啊。

而硬件方面,甚至可以跳过硬件初始化的过程,因为DOS已经初始化好了。但是为了给大家一个比较完整的概念,Lenix还是会对基本的硬件进行初始化,其实最主要的就是初始化8259中断控制器和时钟。别的硬件暂时还不用。在正式进入操作系统理论学习前,还是要进行一个基础训练的。

实验环境嘛,现在虚拟机很多,任选一个就可以,我选择了VPC,因为VPC的文件夹共享功能很方便。我是把一个文件夹设置为VPC中的一个盘,用VS写程序,然后在VPC的DOS中进行编译。可以方便的利用当前方便的工具。

第一个基础是:直接写屏。

感觉比较怪异吧?为什么是这个呢?这时因为,直接写屏是为了调试。调试就要输出信息,直接写屏是输出信息的第一步。所以直接写屏程序是写操作系统第一步。

定义一个变量

word_t con_attr;

这个变量是显示属性,可以通过改变这个变量来改变字符的显示状态。

word_t类型是在type.h文件中定义的

typedef unsigned char byte_t;

typedef unsigned short word_t;

定义几个函数

/*
*  Con_write_byte:向屏幕指定位置写入一个字节
*/
void        Con_write_byte(int pos,const byte_t dat)
{
pos *= 2;                   /*  计算具体的内存地址,相对显存起始地址  */

asm{
mov     bx,pos;
mov     ax,con_attr;
push    es  ;           /*  保存ES段寄存器      */
mov     dx,0B800h
mov     es,dx;          /*  将ES设置为显存段    */
mov     al,dat
mov     es:[bx],ax;     /*  写显存              */
pop     es;             /*  恢复ES段寄存器      */
}
}

/*
*  Con_cls:清屏。
*/
void        Con_cls(void)
{
int x = 0;

while ( x < 80*25 )
Con_write_byte(x++,0x0720);
}

/*
*  Con_write_string:向屏幕输出数据,遇到0则停止输出,但是数据不一定是字符串,当然,我的本意是输出字符串。
*/
int         Con_write_string(int x,int y ,const char * string)
{
const char * str;

str = string;
x  += y * 80;

while( *str)
Con_write_byte(x++,(const byte_t)*str++);

return str - string;
}

/*
*  Con_write:向屏幕输出指定长度的数据,不一定是字符。
*/
void        Con_write(int x,int y,const byte_t * buffer,int size)
{
x  += y * 80;

for( ;size--; )
Con_write_byte(x++,*buffer++);
}


测试一下:

void main(void)
{
Con_cls();
Con_write_string(40,10,"lenix write consol");
}


看看测试结果



在这里,假设显示模式是80*25。

直接写屏,其实就是直接操作显存,在通常情况下,显存是安排在物理内存0xB8000处,在字符模式下,每个字符用两个字节表示,高字节是显示属性,用来控制字符的前景和背景,低字节就是字符本身。具体的格式这里就不画了,如果出书了,在书上画。

在处理显存的时候,直接将段寄存器设置为B800,利用CPU处理地址的方式,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: