若何编写操作系统.docx

上传人:夺命阿水 文档编号:1307373 上传时间:2024-06-05 格式:DOCX 页数:11 大小:39.28KB
返回 下载 相关 举报
若何编写操作系统.docx_第1页
第1页 / 共11页
若何编写操作系统.docx_第2页
第2页 / 共11页
若何编写操作系统.docx_第3页
第3页 / 共11页
若何编写操作系统.docx_第4页
第4页 / 共11页
若何编写操作系统.docx_第5页
第5页 / 共11页
点击查看更多>>
资源描述

《若何编写操作系统.docx》由会员分享,可在线阅读,更多相关《若何编写操作系统.docx(11页珍藏版)》请在课桌文档上搜索。

1、若何编写自己的操作系统有人可能担忧自己既没有学过计算机原理,也没有学过操作系统原理,更不懂汇编语言,对C语言也一知半解,能写操作系统吗答案是没问题。我将带大家一步一步完成自己的操作系统。当然如果学一学上述内容再好不过。首先要明确处理器(也就是CPU)控制着计算机。对PC而言,启动的时候,CPU都处在实模式状态,相当于只是一个Intel8086处理器。也就是说,即使你现在拥有一个奔腾处理器,它的功能也只能是8086级别。从这一点上来讲,可以使用一些软件把处理器转换到著名的保护模式。只有这样,我们才可以充分利用处理器的强大功能。编写操作系统开场是对BIOS控制,取出存储在ROM里的程序。BIOS是

2、用来执行POST(PowerOnSelfTest,自检)的。自检是检查计算机的完整性(比方外设是否工作正常、键盘是否连接等)。这一切完成以后,你就会听到PC喇叭发出一声清脆的响声。如果一切正常,BloS就会选择一个启动设备,并且读取该设备的第一扇区(即启动扇区),然后控制过程就会转移到指定位置。启动设备可能是一个软盘、光盘、硬盘,或者其它所选择的设备。在此我们把软盘作为启动设备。如果我们已经在软盘的启动扇区里写了一些代码,这时它就被执行。因此,我们的目的很明确,就是往软盘的启动扇区写一些程序。首先使用8086汇编来写一个小程序,然后将其拷贝至软盘的启动扇区。为了实现拷贝,要写一个C程序。最后,

3、使用软盘启动计算机。需要的工具 as86:这是一个汇编程序,它负责把写的代码转换成目标文件。 ld86:这是一个连接器,as86产生的目标代码由它来转换成真正的机器语言。机器语言是8086能够解读的形式。 GCC:著名的C编程器。因为我们需要写一个C程序将自己的OS转移到软盘中。 一张空软盘:它用于存储编写的操作系统,也是启动设备。 一台装有LinUX的计算机:这台机器可以很旧,386、486都可以。在大局部标准Linux发行版中都会带有as86和ld86.在我使用的RedHat73中就包含有这两个工具,并且在默认的情况下,它已经安装在机器里。如果使用的LinUX没有这两个工具,可以从网上下载

4、(:/cix.co.uk/mayday/),这两个工具都包含在一个名为bin86的软件包中。此外,有关的文档也可以在网上获得(linux.orgdocsldphowtoAssembly-HOWTOas86.html)o开场工作使用一个你喜欢的编辑器输入以下内容:entrystartstart:movax,#Oxb8OOmoves,axsegesmov0,#0x41segesmovl,#OxlfIoopkjmpIoopl这是as86可以读懂的一段汇编程序。第一个句子指明了程序的入口点,声明整个过程从Start处开场。第二行指明了start的位置,说明整个程序要从start处开场执行。0xb800

5、是显存的开场地址。#说明其后是一个立即数。执行语句:movax,#oxb800ax存放器的值就变为0xb800,这就是显存的地址。下面再将这个值移至es存放器,es是附加段存放器。请记住8086有一个分段的体系构造。它的各段存放器为代码段、数据段、堆栈段和附加段,对应的存放器名称分别为cs、ds、SS和es。事实上,我们把显存地址送入了附加段,因此,任何送入附加段的东西都会被送到显存中。要在屏幕上显示字符,就需要向显存中写两个字节。前一个是所要显示字符的ASeIl值,第二个字节表示该字符的属性。属性包括字符的前风光、背风光及是否闪烁等等。SegeS指明下一个将要执行的指令是指向es段的。所以,

6、我们把值0x41(在ASCn中表示的字符是A)送到显存的第一个字节中。接下来要把字符的属性送到下一个字节当中。在此输入的是OXlf,该属性指的是在蓝色背景下显示白色的字符。因此,如果执行这个程序,就可以在屏幕上得到显示在蓝底上的一个白色的Ao接着是一个循环。因为在执行完显示字符的任务后,要么让程序完毕,要么使用一个循环使其永远运行下去。把该文件命名为boots然后存盘。2若何编写自己的操作系统此处显存的概念说得不是很清楚,有必要进一步解释一下。假设屏幕由80列X25行组成,那么第一行就需要160字节,其中一个字节用于表示字符,另外一个字节用于表示字符的属性。如果要在第三行显示某一字符的话,就要

7、跳过显存的第。和1字节(它们是用于显示第1列的),第2和3字节(它们是用于显示第2列的),然后把需要显示字符的ASCIl码值入第4字节,把字符的属性写入第5字节。把程序写至启动扇区下面写一个C程序,把我的操作系统写入软盘第一扇区。程序内容如下:#include*unistd.h需要这个文件*/#include/*包含有read和write函数*/#includeintmain()charboot-buf512;intfloppy_desc,file_desc;file_desc=open(,.boot,O_RDONLY);read(file_desc,boot_buf,510);close(f

8、ile_desc);boot_buf510=0x55;boot_buf511=Oxaa;floppy_desc=open(,7devfd0,0_RDWR);lseek(floppy_desc,0,SEEK_CUR);Write(floppy_desc,boot_buf,512);close(floppy_desc);)首先,以只读模式翻开boot文件,然后在翻开文件时把文件描述符复制到file_desc变量中。从文件中读取510个字符,或者读取直到文件完毕。在本例中由于文件很小,所以是读取至文件完毕。然后关闭文件。最后4行代码翻开软盘驱动设备(一般来说是devfd)使用Iseek找到文件开场处

9、,然后从缓冲中向软盘写512个字节。在read、write.OPen和ISeek的帮助页中,可以看到与函数所有有关的参数及其使用方法。程序中有两行比较难懂:boot_buf510=0x55;boot_buf511=Oxaa;该信息是用于BloS的,如果它识别出该设备是一个可启动的设备,那么在第510和511的位置,该值就应该是0x55和Oxaa0程序会把文件boot读至名为boot_buf的缓冲中。它要求改变第510和第511字节,然后把boojbuf写至软盘之上。如果执行代码,软盘上的前512字节就包含了启动代码。最后,把文件存为Write.c。编译运行使用下面的命令把文件变为可执行文件:a

10、s86boot.s-oboot.oId86-dboot.o-obootccwrite.c-owrite首先将boot.s文件编译成目标文件boot.o,然后将该文件连接成最终的boot文件。最后C程序编译成可执行的write文件。插入一个空白软盘,运行以下程序:./write重新启动电脑,进展BIOS的界面设置,并且把软盘设为第一个启动的设备。然后插入软盘,电脑从软盘上启动。启动完成后,在屏幕上可以看到一个字母A(蓝底白字),启动速度很快,几乎是在瞬间完成。这就意味着系统已经从我们制作的软盘上启动了,并且执行了刚刚写入启动扇区的程序。现在,它正处在一个无限循环的状态。所以,如果想进入LinUX

11、,必需拿掉软盘,并且重启机器。至此,这个操作系统就算完成了,虽然它没有实现什么功能,但是它己经可以启动机器了。下一期我将在这个启动扇区程序里参加一些代码,使它可以做一些比较复杂的事情(比方使用BK)S中断、保护模式切换等等)。自己动手写操作系统(二)伊梅上一期,我讲述了若何在软盘的启动扇区写一些代码,然后再从软盘启动的过程。制作好一个启动扇区,在切换到保护模式之前,我们还应该知道若何使用BloS中断。BloS中断是一些由BloS提供的、为了使操作系统的创立更容易的低级程序。在本文中,我们将学习处理BIoS的中断。为什么要用BIOSBIOS会把启动扇区拷贝至RAM中,并且执行这些代码。除此之外,

12、BIOS还要做很多其它的事情。当一个操作系统刚开场启动时,系统中并没有显卡驱动、软盘驱动等任何驱动程序。因此,启动扇区中不可能包含任何一个驱动程序,我们要采取其它的途径。这个时候,BloS就可以帮助我们了。BlOS中包含有各种可以使用的程序,包括检测安装的设备、控制打印机、计算内存大小等用于各种目的的程序。这些程序就是所说的BIOS中断。3若何编写自己的操作系统若何调用BIOS中断在一般的程序设计语言中,函数的调用是一件非常容易的事情。比方在C语言中,如果有一个名为display的程序,它带有两个参数,其中参数noofchar表示显示的字符数,参数attr表示显示字符的属性。那么要调用它,只需

13、给出程序的名称即可。对于中断的调用,我们使用的是汇编语言中的int指令。比方,在C语言中要显示一些东西时,使用的指令如下所示:display(nofchar,attr);而使用BIOS时,要实现一样功能使用的指令如下:intOxlO若何传递参数在调用BloS中断之前,我们需要先往存放器中送一些特定的值。假设要使用BIOS的中断13h,该中断的功能是把数据从软盘传送至内存之中。在调用该中断之前,要先指定拷贝数据的段地址,指定驱动器号、磁道号、扇区号,以及要传送的扇区数等等。然后,就要往相应的存放器送入相应的值。在进展下面的步骤前,读者有必要对这一点有比较明确地认识。此外,一个比较重要的事实是同一

14、个中断往往可以实现各种不同的功能。中断所实现确实切功能取决于所选择的功能号,功能号一般都存在ah存放器之中。比方中断13h可以用于读磁盘、写磁盘等功能,如果把3送入ah存放器中,那么中断选择的功能就是写磁盘;如果把2送入ah存放器中,选择的功能那么是读磁盘等。我们要做的事情这次我们的源代码由两个汇编语言程序和一个C程序组成。第一个汇编文件是引导扇区的代码。在引导扇区中,我们写的代码是要把软盘中第二扇区拷贝至内存段的0x500处(地址是0x5000,即偏移地址为0)。这时我们需要使用BloS的中断13h。这时启动扇区的代码就会把控制权转移至0x500处。在第二个汇编文件中,代码会使用BIOS中断

15、IOh在屏幕上显示一个信息。C程序实现的功能那么是把可执行的文件1拷贝至启动扇区,把可执行的文件2拷贝至软盘的第二扇区。启动扇区代码使用中断13h,启动扇区把软盘第二扇区里的内容加载至内存的0x5000处(段地址为0x500)。下面的代码是用于实现这一目的的代码,将其保存至文件sbect.s中。1.OC1=0x500entrystartstart:movax,#LOClmoves,axmovbx,#Omovdl,#0movdh,#Omovch,#Omovcl,#2moval,#lmovah,#2int0x13jmpi0,#LOC1上面代码第一行类似于一个宏。接下去的两行那么是把值0x500加载

16、至es存放器中,这是软盘上第二扇区代码将拷贝到的地方(第一扇区是启动扇区)。这时,把段内的偏移设为Oo接下来把驱动器号送入di存放器中,其中磁头号送入dl存放器中,磁道号送入ch存放器中,扇区号送入cl存放器中,扇区数送入al存放器之中。我们想要实现的功能是把扇区2、磁道号为0、驱动器号为0的内容送至段地址0x500处。所有这些参数都和1.44MB的软盘相对应把2送入ah存放器中,是选择了由中断13h提供的相应功能,即实现从软驱转移数据的功能。最后调用中断13h,并且转至偏移为0的段地址0x500处。第二个扇区的代码第二个扇区中的代码如下所示(把这些代码保存至文件sbect2.s之中):ent

17、rystartstart:movah,#0x03xorbh,bhint0x10movex,#26movbx,#0x0007movbp,#mymsgmovax,#0x!301intOxlOIoopkjmpIooplmymsg:.byte13,10.asciiOperatingSystemisLoading上面代码将被加载至段地址为0x500处,并且被执行。在这段代码中,使用了中断IOh来获取目前的光标位置,然后显示信息。从第3行到第5行用于得到目前光标的位置,在此中断IOh选用的是功能3。然后,去除了bh存放器的内容,并把字符串送至Ch存放器中。在bx中,我们送入了页码及显示的属性。此处,我们想

18、要在黑背景上显示白色的字符。然后,把要显示字符的地址送到bp之中,信息由两个字节组成,其值分别为13的10,它们分别对应回车和LF(换行)的ASCll值。接下来是一个由29个字符组成的串;在下面实现的功能是输出字符串然后移动光标;最后是调用中断,然后进入循环。4若何编写自己的操作系统C程序代码C程序的源代码如下所示,将其存储为Write.c文件。#include*unistd.hneedsthis*/#include*containsread/write*/#includeintmain()(charboot_buf512;intfloppy_desc,file_desc;file_desc=

19、open(,bsect,O_RDONLY);read(file_desc,boot_buf,510);close(file_desc);boot_buf51OJ=0x55;boot_buf511=Oxaa;floppy_desc=open(,7devfd0,0_RDWR);lseek(floppy_desc,0,SEEK_SET);Write(floppy_desc,boot_buf,512);file_desc=open(,.sect2,O_RDONLY);read(file_desc,boot_buf,512);close(file_desc);ISeek(floppy_desc,512,

20、SEEK_SET);Write(floppy_desc,boot_buf,512);close(floppy_desc);在上一期中,我曾经介绍过若何操作能启动的软盘。现在这一个过程稍微有点不同,首先把由bsect.s编译出来的可执行文件bsect拷贝至软盘的启动扇区。然后再把由sect2.s产生的可执行文件sect2拷贝至软盘的第二个扇区。把上述文件置于同一目录之下,然后分别对其进展编译,方法如下所示:as86bsect.s-obsect.oId86-dbsect.o-obsect对sect2.s文件重复以上的操作,得出可执行文件SeCt2。编译Write.c,插入软盘后执行Write文件,

21、命令如下所示:ccwrite.c-owrite./write下一步我们要做的事情从软盘启动以后,可以看到显示出来的字符串。这是使用了BloS中断来完成的。下一期要做的事情是在这个操作系统中实现实模式向保护模式的转换。自己动手写操作系统(三)在上两期中(自己动手写操作系统1,2),我向大家讲述了若何使用LinUX提供的开发工具在软盘的启动扇区写一些代码,以及若何调用BIOS的问题。现在,这个操作系统己经越来越接近当年LinusTorvalds的那个具有“历史意义”的LinUX内核了。因此,要马上把这个系统切换到保护模式之下。什么是保护模式自从1969年推出第一个微处理器以来,Intel处理器就在

22、不断地更新换代,从8086、8088、80286,到80386、80486、奔腾、奔腾II、奔腾4等,其体系构造也在不断变化。80386以后,提供了一些新的功能,弥补了8086的一些缺陷。这其中包括内存保护、多任务及使用640KB以上的内存等,并仍然保持和8086家族的兼容性。也就是说80386仍然具备了8086和80286的所有功能,但是在功能上有了很大的增强。早期的处理器是工作在实模式之下的,80286以后引入了保护模式,而在80386以后保护模式又进展了很大的改进。在80386中,保护模式为程序员提供了更好的保护,提供了更多的内存。事实上,保护模式的目的不是为了保护程序,而是要保护程序以

23、外的所有程序(包括操作系统)。简言之,保护模式是处理器的一种最自然的模式。在这种模式下,处理器的所有指令及体系构造的所有特色都是可用的,并且能够到达最高的性能。保护模式和实模式从外表上看,保护模式和实模式并没有太大的区别,二者都使用了内存段、中断和设备驱动来处理硬件,但二者有很多不同之处。我们知道,在实模式中内存被划分成段,每个段的大小为64KB,而这样的段地址可以用16位来表示。内存段的处理是通过和段存放器相关联的内部机制来处理的,这些段存放器(CS.DS、SS和ES)的内容形成了物理地址的一局部。具体来说,最终的物理地址是由16位的段地址和16位的段内偏移地址组成的。用公式表示为:物理地址

24、=左移4位的段地址+偏移地址。在保护模式下,段是通过一系列被称之为”描述符表”的表所定义的。段存放器存储的是指向这些表的指针。用于定义内存段的表有两种:全局描述符表(GDT)和局部描述符表(LDT).GDT是一个段描述符数组,其中包含所有应用程序都可以使用的基本描述符。在实模式中,段长是固定的(为64KB),而在保护模式中,段长是可变的,其最大可达4GB。LDT也是段描述符的一个数组。与GDT不同,1.DT是一个段,其中存放的是局部的、不需要全局共享的段描述符。每一个操作系统都必须定义一个GDT,而每一个正在运行的任务都会有一个相应的LDTo每一个描述符的长度是8个字节,格式如图3所示。当段存

25、放器被加载的时候,段基地址就会从相应的表入口获得。描述符的内容会被存储在一个程序员不可见的影像存放器(ShadOWregister)之中,以便下一次同一个段可以使用该信息而不用每次都到表中提取。物理地址由16位或者32位的偏移加上影像存放器中的基址组成。实模式和保护模式的不同可以从图1和图2中很清楚地看出来。5若何编写自己的操作系统图I实模式的寻址图2保护模式下的寻址图3段描述俯的格式此外,还有一个中断描述符表(IDT)。这些中断描述符会告诉处理器到那里可以找到中断处理程序。和实模式一样,每一个中断都有一个入口,但是这些入口的格式却完全不同。因为在切换到保护模式的过程中没有使用到1DT,所以在

26、此就不多做介绍了。进入保护模式80386有4个32位控制存放器,名字分别为CRO、CRI、CR2和CR3。CRl是保存在未来处理器中使用的,在80386中没有定义。CRo包含系统的控制标志,用于控制处理器的操作模式和状态。CR2和CR3是用于控制分页机制的。在此,我们关注的是CRO存放器的PE位控制,它负责实模式和保护模式之间的切换。当PE=I时,说明处理器运行于保护模式之下,其采用的段机制和前面所述的相应内容对应。如果PE=O,那么处理器就工作在实模式之下。切换到保护模式,实际就是把PE位置为1。为了把系统切换到保护模式,还要做一些其它的事情。程序必须要对系统的段存放器和控制存放器进展初始化

27、。把PE位置1后,还要执行跳转指令。过程简述如下:1 .创立GDT表;2 .通过置PE位为1进入保护模式;3 .执行跳转以去除在实模式下读取的任何指令。下面使用代码来实现这个切换过程。需要的东西 一张空白软盘 NASM编译器下面是整个程序的源代码:org0x07c00;起始地址是0000:7c00jmpshortbegin.boot;跳过其它的数据,跳转到引导程序的开场处bootmesgdbOurOSbootsectorloading,pm_mesgdbSwitchingtoprotectedmode.dw512;每一扇区的字节数dbI;每一簇的扇区数dw1;保存的扇区号db2dwOxOOeO

28、dw0x0b40dbOxOfDdw9dw18dw2;读写扇区号dw0;降藏扇区号print_mesg:movah,0x13;使用中断IOh的功能13,在屏幕上写一个字符串moval,0x00;决定调用函数后光标所处的位置movbx,0x0007;设置显示属性movex,0x20;在此字符串长度为32movdx,0x0000;光标的起始行和列int0x10;调用BIOS的中断IOhret;返回调用程序get_key:movah,0x00intOx16;GeLkey使用中断I6h的功能0,读取下一个字符retclrscr:movax,0x0600;使用中断Ioh的功能6,实现卷屏,如果al=0那么

29、清屏movex,0x0000;清屏movdx,0xl74f;卷屏至23,79movbh,0;使用颜色0来填充int0x10;调用IOh中断retbegin_boot:callclrscr;先清屏movbp,bootmesg;提供串地址callprint_mesg;输出信息callget_key;等待用户按下任一键bits16callCIrSCI;清屏movax,0xb800;使gs指向显示内存movgs,ax;在实模式下显示一个棕色的Amovwordlgs:O,0x641;显示callget_key;调用Get_key等待用户按下任一键movbp,pm_mesg;设置串指针callPrinLm

30、eSg;调用print_mesg子程序callget_key;等待按键callclrscr;清屏cli;关中断gdtgdtr;加载GDTmoveax,croral,0x01;设置保护模式位movcr,eax;将更改后的字送至控制存放器中jmpcodesei:go_pmbits32go_pm:movax,dataselmovds,ax;初始化ds和es,使其指向数据段moves,axmovax,videosel;初始化gs,使其指向显示内存movgs,axmovwordgs:O,0x741;在保护模式下显示一个白色的字符Aspin:jmpspin;循环bits16gdtr:dwgdt_end-g

31、dt-l;gdt的长度ddgdt;gdt的物理地址gdtnullselequ$-gdt;$指向当前位置,所以nullsel=Ohgdt;空描述符dddd;所有的段描述符都是64位的codeseiequ$-gdt;这是8h也就是gdt的第二个描述符6若何编写自己的操作系统codegdtdwOxOffff;段描述符的界限是4GbdwOxOOOOdb0x00db0x09adbOxOcfdbOxOOdataselequ$-gdtdata_gdtdwOxOffffdwOxOOOOdbOxOOdb0x092dbOxOcfdbOxOOvideoseiequ$-gdtdw3999dw0x8000;基址是0xb

32、8000dbOxObdb0x92dbOxOOdbOxOOgdt_endtimes510-($-$)dbdw0x0aa55把上面的代码存在一个名为abc.asm的文件之中,使用命令nasmabc.asm,将得出一个名为abc的文件。然后插入软盘,输入命令:ddif=abcOf=ZdevZfdOo该命令将把文件abc写入到软盘的第一扇区之中。然后重新启动系统,就会看到如下的信息:*0urosbooting*A(棕色)*Switchingtoprotectedmode.*A(白色)对代码的解释上面给出了所有的代码,下面我对上述代码做一些解释。使用的函数下面是代码中一些函数的说明:print_mesg

33、该子程序使用了BloS中断IOh的功能13h,即向屏幕写一字符串。属性控制是通过向一些寄存器中送入不同的值来实现的。中断IOh是用于各种字符串操作,我们把子功能号13h送到ah中,用于指明要打印一个字符串。al存放器中的0说明了光标返回的起始位置,0表示调用函数后光标返回到下一行的行首。如果al为1那么表示光标位于最后一个字符处。显存被分成了几页,在同一时刻只能显示其中的一页。bh指明的是页号;bl那么指明要显示字符的颜色:CX指明要显示字符串的长度;dx指明光标的位置(即起始的行和列)。所有相关存放器初始化完成以后,就可以调用BIOS中断IOh了。get,key使用中断16h的子功能OOh,

34、从屏幕得到下一个字符。Clrscr该函数使用了中断IOh的另外一个子功能06h,用于输出开场前清屏。初始化时给al中送入0。存放器CX和dx指明要清屏的屏幕范围,在本例中是整个屏幕。存放器bh指明屏幕填充的颜色,在本例中是黑色。其它内容程序一开场是一条短跳转指令,跳到beginjxot处。在实模式下,在此打印一个棕色的“A”,并且设置一个GDT。切换到保护模式,并且打印一个白色的“A”。这两种模式使用的都是自己的寻址方法。在实模式下,使用段存放器gs指示显存位置,我们使用的是CGA显卡(默认基址是0xb8000)o在代码中是不是漏了一个0呢没有,因为实模式下会提供一个附加的0。这种方式也被80

35、386继承下来了。A的ASCII是0x41,0x06指明了需要一个棕色的字符。该显示会一直持续直至按下任意键。下面要在屏幕上显示一句话,告诉使用者下面马上要进入保护模式了。启动到保护模式,在进展切换时不希望此时有中断的影响,故要关闭所有的中断(使用Cli来实现)。然后对GDT初始化。在整个切换过程中,对4个描述符进展了初始化。这些描述符对代码段(COde_gdt)、数据和堆栈段(data-gdt),以及为了访问显存而对显示段进展初始化。此外,还会对一个空描述符进展初始化。GDT的基址要加载至GDTR系统存放器之中。gdtr段的第一个字加载的是GDT的大小,在下一个双字中那么加载的是基址。然后,

36、Igdt指令把把gdt段加载至GDTR存放器中。现在己经做好了切换到保护模式前的所有准备。最后一件事情就是把CRO存放器的PE位置I。不过,即使这样还没有处于保护模式状态之下。设置了PE位以后,还需要通过执行JMP指令来去除处理器指令预取队列。在80386中,使用指令前总是先将其从内存中取出,并且进展解码和寻址。然而,当进入保护模式以后,预取指令信息(它还处于实地址模式)就无效了。使用JMP指令的目的就是强迫处理器放弃无效的信息。现在,已经在保护模式下了。那么,若何检测是在保护模式状态之下呢让我们来看一看屏幕上这个白色的字母A。在这里,使用了数据段选择符(datasel)对数据段和附加段进展了初始化,使用显示段选择符(VideOSeD对gs进展了初始化。告示的字符“A其ASCIl值和属性位于gs:OOo0处,也就是b8000:0000处。循环语句使得该字符一直在屏幕上显示,直至重新启动系统。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 在线阅读 > 生活休闲


备案号:宁ICP备20000045号-1

经营许可证:宁B2-20210002

宁公网安备 64010402000986号