﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-旅途-随笔分类-一步一步操作系统</title><link>http://www.cppblog.com/mydriverc/category/5934.html</link><description>如果想飞得高，就该把地平线忘掉</description><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 13:36:18 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 13:36:18 GMT</pubDate><ttl>60</ttl><item><title>小试编写操作系统 1</title><link>http://www.cppblog.com/mydriverc/archive/2008/01/08/40739.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Tue, 08 Jan 2008 08:52:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/archive/2008/01/08/40739.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/40739.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/archive/2008/01/08/40739.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/40739.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/40739.html</trackback:ping><description><![CDATA[
		<p>按照于渊的书还有网上的文章<br /><br /><strong>1 使用VM建立一个虚拟机，一路other,32M内存即可<br />2 在edit virtual mathine setting中删除所有的设备（除了内存）<br />3 选择add添加设备 floppy driver-&gt;create a blank floppy<br />4 使用nasm编译下面的代码（于渊书上的）</strong><br />org 07c00h ; 告诉编译器程序加载到7c00处</p>
		<p> mov ax, cs</p>
		<p> mov ds, ax</p>
		<p> mov es, ax</p>
		<p> call DispStr ; 调用显示字符串例程</p>
		<p> jmp $ ; 无限循环</p>
		<p>DispStr:</p>
		<p> mov ax, BootMessage</p>
		<p> mov bp, ax ; es:bp = 串地址</p>
		<p> mov cx, 16 ; cx = 串长度</p>
		<p> mov ax, 01301h ; ah = 13, al = 01h</p>
		<p> mov bx, 000ch ; 页号为0(bh = 0) 黑底红字(bl = 0Ch,高亮)</p>
		<p> mov dl, 0</p>
		<p> int 10h ; 10h 号中断</p>
		<p> ret</p>
		<p>BootMessage: db "Hello, OS world!"</p>
		<p>times 510-($-$$) db 0 ; 填充剩下的空间，使生成的二进制代码恰好</p>
		<p>为</p>
		<p>; 512字节</p>
		<p>dw 0xaa55 ; 结束标志<br /><strong>5 使用Floppy Writer将编译过的文件写入前面建立的floppy上。<br />6启动虚拟机。<br />可以看到效果了。<br /><br />下一步该研究引导程序了</strong></p>
<img src ="http://www.cppblog.com/mydriverc/aggbug/40739.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2008-01-08 16:52 <a href="http://www.cppblog.com/mydriverc/archive/2008/01/08/40739.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>csdn上的 自己动手写操作系统</title><link>http://www.cppblog.com/mydriverc/archive/2008/01/07/40636.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Mon, 07 Jan 2008 09:39:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/archive/2008/01/07/40636.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/40636.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/archive/2008/01/07/40636.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/40636.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/40636.html</trackback:ping><description><![CDATA[
		<a href="http://book.csdn.net/bookfiles/88/index.html">http://book.csdn.net/bookfiles/88/index.html</a>
<img src ="http://www.cppblog.com/mydriverc/aggbug/40636.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2008-01-07 17:39 <a href="http://www.cppblog.com/mydriverc/archive/2008/01/07/40636.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux操作系统下的汇编程序设计简介</title><link>http://www.cppblog.com/mydriverc/archive/2008/01/07/40635.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Mon, 07 Jan 2008 09:38:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/archive/2008/01/07/40635.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/40635.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/archive/2008/01/07/40635.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/40635.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/40635.html</trackback:ping><description><![CDATA[
		<div id="BlogArticleDetail" style="FONT-SIZE: 14px">
				<p style="TEXT-INDENT: 2em">
						<b>摘要：</b>本文主要讲述了Linux下使用汇编的利弊，以及常用汇编工具的使用和语法特点。重点讲述了NASM。 </p>
				<p style="TEXT-INDENT: 2em">
						<b>引言：</b>汇编语言是低级语言，与硬件和操作系统紧密联系。个人电脑以前都是用DOS，现在发展成了WINDOWS 98，而另一个操作系统Linux也正在崛起。下面比较一下这三个操作系统： </p>
				<p style="TEXT-INDENT: 2em">DOS较稳定，速度快无法充分发挥计算机性能，没有图形界面较低。 </p>
				<p style="TEXT-INDENT: 2em">WINDOWS 98操作简便，应用软件多,硬件兼容性好；不稳定，经常死机，速度慢高。 </p>
				<p style="TEXT-INDENT: 2em">Linux性能优秀，非常稳定，界面美观，操作简便；缺乏软件厂商支持，应用软件少免费。 </p>
				<p style="TEXT-INDENT: 2em">由以上的比较可知，Linux操作系统本身具有较大优势，它的普及应该只是时间问题，所以如何在Linux下开发软件是我们计算机系学生必须学习与研究的一个课题。 </p>
				<p style="TEXT-INDENT: 2em">Linux 下的主要编程语言是C，同时Linux还支持其他许多编程语言，汇编语言作为最重要的编程语言之一，当然也包括在内。它能够完成许多其他语言所不能完成的功能。要学习Linux编程，就必须要学习Linux下的汇编程序设计。下面我就来介绍一下Linux下的汇编程序设计。 </p>
				<p style="TEXT-INDENT: 2em">
						<b>Linux汇编简介</b>
				</p>
				<p style="TEXT-INDENT: 2em">
						<b>一、汇编语言的优缺点</b>
				</p>
				<p style="TEXT-INDENT: 2em">由于Linux是用C写的，所以C自然而然的就成为了Linux的标准编程语言。大部分人都把汇编给忽略了，甚至在因特网上找资料都是非常的困难，很多问题都需要靠自己来尝试。我认为这样对待汇编语言是不公平的，不能只看到它的缺点，当然也不能只看到它的优点，下面把它的优缺点作一个比较： </p>
				<p style="TEXT-INDENT: 2em">优点：汇编语言可以表达非常底层的东西 </p>
				<p style="TEXT-INDENT: 2em">可以直接存取寄存器和I/O； </p>
				<p style="TEXT-INDENT: 2em">编写的代码可以非常精确的被执行； </p>
				<p style="TEXT-INDENT: 2em">可以编写出比一般编译系统高效的代码； </p>
				<p style="TEXT-INDENT: 2em">可以作为不同语言或不同标准的接口。 </p>
				<p style="TEXT-INDENT: 2em">缺点：汇编语言是一个非常低级的语言 </p>
				<p style="TEXT-INDENT: 2em">非常冗长单调，在DOS下编程时就可以体会到； </p>
				<p style="TEXT-INDENT: 2em">易出BUG，且调试困难； </p>
				<p style="TEXT-INDENT: 2em">代码不易维护； </p>
				<p style="TEXT-INDENT: 2em">兼容性不好，与硬件关系非常紧密。 </p>
				<p style="TEXT-INDENT: 2em">总的来说，汇编语言要用在必须的地方，尽量少用汇编编写大型程序，多采用inline模式。 </p>
				<p style="TEXT-INDENT: 2em">
						<b>二、汇编语言工具</b>
				</p>
				<p style="TEXT-INDENT: 2em">DOS 下常用的工具MASM和TASM到Linux下就用不起来了，Linux有自己的汇编工具，而且种类非常的多。其中Gas可以算是标准配置，每一种 Linux中都包括有Gas，但是GAS采用的不是我们通常在DOS下采用的汇编语法，它采用的是AT＆T的语法格式，与intel语法格式有很大的不同。 </p>
				<p style="TEXT-INDENT: 2em">如果要采用与DOS接近的语法格式，就必须用另一种汇编工具NASM，NASM基本与MASM相同，但也有不少地方有较大区别，特别涉及到操作系统原理时，与DOS可以说是截然不同。 </p>
				<p style="TEXT-INDENT: 2em">
						<b>Linux汇编程序设计</b>
				</p>
				<p style="TEXT-INDENT: 2em">一、Hello,world! </p>
				<p style="TEXT-INDENT: 2em">几乎所有的语言入门篇都是以“Hello,world!”为例，那么我也以Hello,world!为例开始。 </p>
				<p style="TEXT-INDENT: 2em">
				</p>
				<center>
						<ccid_nobr>
								<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
										<tbody>
												<tr>
														<td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6">
																<pre>
																		<ccid_code>NASM's standalone Hello-World.asm for Linux 
section .text
extern puts
global main

main: 
push dword msg ;stash the *** of msg on the stack.
call puts ;call the 'puts' routine (libc?) 
add esp, byte 4 ;clean the stack?
ret ;exit.

msg:
db "Hello World!",0 

编译：
nasm –f elf hello.asm
gcc –o hello hello.o</ccid_code>
																</pre>
														</td>
												</tr>
										</tbody>
								</table>
						</ccid_nobr>
				</center>
				<p style="TEXT-INDENT: 2em">说明：这个程序实际上是调用了，Linux系统的puts函数，原理与调用DOS下C语言的函数相同，先用Extern声明puts是外部函数，再把参数（即msg的地址）压入堆栈，最后Call函数实现输出。 </p>
				<p style="TEXT-INDENT: 2em">我们再来看一个程序： </p>
				<p style="TEXT-INDENT: 2em">
				</p>
				<center>
						<ccid_nobr>
								<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
										<tbody>
												<tr>
														<td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6">
																<pre>
																		<ccid_code>section .text
global main

main: 
mov eax,4 ;4号调用
mov ebx,1 ;ebx送1表示stdout
mov ecx,msg ;字符串的首地址送入ecx
mov edx,14 ;字符串的长度送入edx
int 80h ;输出字串
mov eax,1 ;1号调用
int 80h ;结束
msg:
db "Hello World!",0ah,0dh 
（编译同上一个程序）</ccid_code>
																</pre>
														</td>
												</tr>
										</tbody>
								</table>
						</ccid_nobr>
				</center>
				<p style="TEXT-INDENT: 2em">这个程序与DOS程序十分相似，它用的是linux中的80h中断，相当于DOS下的21h中断，只是因为Linux是32位操作系统，所以采用了 EAX、EBX等寄存器。但是Linux作为一个多用户的操作系统与DOS又是有着非常大的区别的。要写出有特色的程序，不了解操作系统和硬件是不行的。下面我介绍一下Linux操作系统。 </p>
				<p style="TEXT-INDENT: 2em">
						<b>二、Linux操作系统简介</b>
				</p>
				<p style="TEXT-INDENT: 2em">操作系统实际是抽象资源操作到具体硬件操作细节之间的接口。对Linux这样的多用户操作系统来说，它需要避免用户对硬件的直接访问，并防止用户之间的互相干扰。所以Linux接管了 BIOS调用和端口输入输出，关于端口输入输出方面请参阅Linux IO-Port-Programming HOWTO。而要通过Linux对硬件硬件进行访问就需要用到System Call，实际上是许多C的函数，可以在汇编程序中调用，调用方法与DOS下的汇编完全相同，而且用ASM汇编时不用链接额外的库函数。 </p>
				<p style="TEXT-INDENT: 2em">Linux与DOS的主要区别在于内存管理、进程（DOS下无进程概念）、文件系统，其中内存管理和进程与汇编编程的关系比较密切： </p>
				<p style="TEXT-INDENT: 2em">
						<b>1、内存管理</b>
				</p>
				<p style="TEXT-INDENT: 2em">对任一台计算机而言，其内存以及其他资源都是有限的。为了让有限的物理内存满足应用程序对内存的大需求量，Linux采用了称为“虚拟内存”的内存管理方式。Linux将内存划分为容易处理的“内存页”，在系统运行过程中，应用程序对内存的需求大于物理内存时，Linux可将暂时不用的内存页交换到硬盘上，这样，空闲的内存页可以满足应用程序的内存需求，而应用程序却不会注意到内存交换的发生。 </p>
				<p style="TEXT-INDENT: 2em">
						<b>进程</b>
				</p>
				<p style="TEXT-INDENT: 2em">进程实际是某特定应用程序的一个运行实体。在Linux系统中，能够同时运行多个进程，Linux通过在短的时间间隔内轮流运行这些进程而实现“多任务”。这一短的时间间隔称为“时间片”，让进程轮流运行的方法称为“调度”，完成调度的程序称为调度程序。通过多任务机制，每个迸程可认为只有自己独占计算机，从而简化程序的编写，每个进程有自己单独的地址空间，并且只能由这一进程访问，这样，操作系统避免了进程之间的互相干扰以及“坏”程序对系统可能造成的危害。 </p>
				<p style="TEXT-INDENT: 2em">为了完成某特定任务，有时需要综合两个程序的功能，例如一个程序输出文本，而另一个程序对文本进行排序。为此，操作系统还提供进程间的通讯机制来帮助完成这样的任务。Linux中常见的进程间通讯机制有信号、管道、共享内存、信号量和套接字等。 </p>
				<p style="TEXT-INDENT: 2em">
						<b>三、Linux下的汇编工具</b>
				</p>
				<p style="TEXT-INDENT: 2em">Linux下的汇编工具可谓百家争鸣，不像DOS下都要给MASM和TASM给控制了。但是Linux下每一种汇编工具都有很大的区别，要想全部掌握几乎是不可能的，下面我介绍几种常用的汇编工具，重点介绍NASM及其使用和语法。 </p>
				<p style="TEXT-INDENT: 2em">1、GCC </p>
				<p style="TEXT-INDENT: 2em">GCC其实是GNU的C语言产品，但它支持Inline Assemble，在GCC中inline assemble使用就像宏一样，但它比宏能更清楚更准确的表达机器的工作状态。 </p>
				<p style="TEXT-INDENT: 2em">C是汇编编程的一个高度概括，它可以减少许多汇编中的麻烦，特别是在GCC这个C编译器中，assemble似乎起不了多大的作用。 </p>
				<p style="TEXT-INDENT: 2em">2、GAS </p>
				<p style="TEXT-INDENT: 2em">GAS 是Linux各版本中基本的汇编工具，但它采用的是AT&amp;T的语法标准与Intel的语法标准有很大的不同，对于DOS编程的我们来说，学习起来是非常困难的。当然如果要精通Linux下的汇编编程，学习GAS也是非常必要的，具体的语法标准可以参看Using GNU Assembler。 </p>
				<p style="TEXT-INDENT: 2em">3、GASP </p>
				<p style="TEXT-INDENT: 2em">GASP是GAS的扩展，它增强了GAS对宏的支持。 </p>
				<p style="TEXT-INDENT: 2em">4、NASM </p>
				<p style="TEXT-INDENT: 2em">NASM是linux中语法与DOS最为相像的一种汇编工具。虽说如此，它与MASM也是有着很大区别的。 </p>
				<p style="TEXT-INDENT: 2em">l NASM的使用格式如下： </p>
				<p style="TEXT-INDENT: 2em">Nasm –f -o </p>
				<p style="TEXT-INDENT: 2em">例如： </p>
				<p style="TEXT-INDENT: 2em">Nasm -f elf hello.asm </p>
				<p style="TEXT-INDENT: 2em">将把hello.asm汇编成ELF object文件，而Nasm -f bin hello.asm -o hello.com会把hello.asm汇编成二进制可执行文件hello.com.Nasm –h将会列出NASM命令行的完整说明。NASM不会有任何输出，除非有错误发生。-f 在Linux下主要有aout和ELF两种，如果你不确定你的Linux系统应该用AOUT还是ELF，可以在NASM目录中输入 File nasm ，如果输出nasm: ELF 32-bit LSB executable i386 (386 and up) Version 1表示是ELF，如果输出nasm: Linux/i386 demand-paged executable (QMAGIC)表示是aout。 </p>
				<p style="TEXT-INDENT: 2em">NASM与MASM的主要不同： </p>
				<p style="TEXT-INDENT: 2em">首先与linux系统一样，nasm是区分大小写的，Hello与hello将是不同的标识符，如果要汇编到DOS或OS/2，需要加入UPPERCASE参数。 </p>
				<p style="TEXT-INDENT: 2em">其次，nasm中内存操作数都是以[ ]表示。 </p>
				<p style="TEXT-INDENT: 2em">在MASM中 </p>
				<p style="TEXT-INDENT: 2em">
				</p>
				<center>
						<ccid_nobr>
								<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
										<tbody>
												<tr>
														<td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6">
																<pre>
																		<ccid_code>foo equ 1 
bar dw 2
mov ax,foo 
mov ax,bar</ccid_code>
																</pre>
														</td>
												</tr>
										</tbody>
								</table>
						</ccid_nobr>
				</center>
				<p> </p>
				<p style="TEXT-INDENT: 2em">将被汇编成完全不同的指令，虽然它们在MASM中的表达方式完全一样。而NASM完全避免了这种混乱，它使用的是这样的规则：所有对内存的操作都必须通过 [ ]来实现。例如上例中对bar的操作就要写成如下形式 mov ax,[bar]。由此可见，nasm中对offset的使用也是没有必要的（nasm中无offset）。Nasm对[ ]的使用与masm也有所不同，所有的表达式都必须写在[ ]中，下面举两个例子来说明： </p>
				<p style="TEXT-INDENT: 2em">
				</p>
				<center>
						<ccid_nobr>
								<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
										<tbody>
												<tr>
														<td class="code" style="FONT-SIZE: 9pt" bgcolor="#e6e6e6">
																<pre>
																		<ccid_code>Masm Nasm 
Mov ax,table[di]
Mov ax,[table+di]

Mov ax,es:[di]
Mov ax,[es:di]

Mov ax,[di]+1
Mov ax,[di+1]</ccid_code>
																</pre>
														</td>
												</tr>
										</tbody>
								</table>
						</ccid_nobr>
				</center>
				<p style="TEXT-INDENT: 2em">Nasm 中不存储变量类型，原因很简单masm中通过[ ]寻址方式的变量也必须要指定类型。Nasm中不支持LODS, MOVS, STOS, SCAS, CMPS, INS, OUTS，只支持lodsb、lodsw等已经指定类型的操作。Nasm中不再有assume操作，段地址完全取决于存入段寄存器的值。关于NASM的使用方法及语法还可以参阅NASM使用手册。 </p>
				<p style="TEXT-INDENT: 2em">
						<b>结论</b>
				</p>
				<p style="TEXT-INDENT: 2em">我认为不论是在Windows/DOS下还是在Linux下完完全全用汇编编一个大型程序已经是不可能了，也不会有人愿意去这样做。在windows下我们可以用VC，在Linux/Xwindows下我们可以用C甚至C++ Builder，但是像VC、C++ Builder之类的工具尽量隐藏了底层的调用，同时也阻隔了成为高手的机会，因为编出来的程序无法了解它的执行过程也就使编程中最重要的“可预测”性变得很低。正因为如此汇编才有它存在的必要性，同时还有一个更重要的原因，正如《超级解霸》的作者梁肇新所说：“编程序的重点不是“编”，而是调试程序，理论上的完美在实现的时候会遇到很多细节问题，这些问题必须调试才能解决。我的编程习惯是一天写五天调试，《超级解霸》是调试出来的，而不是写出来的。调试就涉及到汇编的问题，不进行汇编级的调试是不彻底的，也不能让人放心。</p>
		</div>
<img src ="http://www.cppblog.com/mydriverc/aggbug/40635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2008-01-07 17:38 <a href="http://www.cppblog.com/mydriverc/archive/2008/01/07/40635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为什么是NASM</title><link>http://www.cppblog.com/mydriverc/archive/2008/01/07/40634.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Mon, 07 Jan 2008 09:37:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/archive/2008/01/07/40634.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/40634.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/archive/2008/01/07/40634.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/40634.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/40634.html</trackback:ping><description><![CDATA[
		<font size="4">
				<font face="宋体">你的疑问是“为什么是</font>
				<span lang="EN-US">
						<font face="Times New Roman">NASM</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而不是</span>
				<span lang="EN-US">
						<font face="Times New Roman">MASM</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”，那么现在你的疑问可能变成了“为什么是</span>
				<span lang="EN-US">
						<font face="Times New Roman">NASM</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而不是</span>
				<span lang="EN-US">
						<font face="Times New Roman">GAS</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”。因为</span>
				<span lang="EN-US">
						<font face="Times New Roman">MASM</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
				<span lang="EN-US">
						<font face="Times New Roman">GAS</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">都太极端了，还是</span>
				<span lang="EN-US">
						<font face="Times New Roman">NASM</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">比较中庸，它既可以在</span>
				<span lang="EN-US">
						<font face="Times New Roman">Windows</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台下使用，又可以在</span>
				<span lang="EN-US">
						<font face="Times New Roman">Linux</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台下使用。而且，如果没有接触过</span>
				<span lang="EN-US">
						<font face="Times New Roman">AT&amp;T</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">格式的汇编，</span>
				<span lang="EN-US">
						<font face="Times New Roman">GAS</font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">看上去实在太奇怪了，入门时一定会让你感到晕头转向。</span>
		</font>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 20pt">
				<font size="4">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在这里，我们总结一下使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">NASM</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的几大理由：</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 20pt">
				<font size="4">
						<span lang="EN-US" style="FONT-FAMILY: 'Wingdings 2'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">
								<span style="mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">—</span>
						</span>
						<font face="Times New Roman">
								<span lang="EN-US" style="FONT-SIZE: 5pt; mso-bidi-font-size: 12.0pt">
										<span style="mso-spacerun: yes">  </span>
								</span>
								<span lang="EN-US">NASM</span>
						</font>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
						<span lang="EN-US">
								<font face="Times New Roman">MASM</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接近，入门比较容易。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 31.2pt; TEXT-INDENT: -11.3pt; mso-char-indent-count: -1.13; mso-para-margin-left: 1.99gd">
				<font size="4">
						<span lang="EN-US" style="FONT-FAMILY: 'Wingdings 2'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">
								<span style="mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">—</span>
						</span>
						<span lang="EN-US">
								<font face="Times New Roman"> NASM</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在不同平台下均可使用，可以在</span>
						<span lang="EN-US">
								<font face="Times New Roman">Windows</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下编写并调试，然后拿到</span>
						<span lang="EN-US">
								<font face="Times New Roman">Linux</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下使用。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 20pt">
				<font size="4">
						<span lang="EN-US" style="FONT-FAMILY: 'Wingdings 2'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">
								<span style="mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">—</span>
						</span>
						<span lang="EN-US">
								<font face="Times New Roman">
								</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">自带反汇编程序，方便取用。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 20pt">
				<font size="4">
						<span lang="EN-US" style="FONT-FAMILY: 'Wingdings 2'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">
								<span style="mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">—</span>
						</span>
						<span lang="EN-US">
								<font face="Times New Roman">
								</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文档丰富，自带的文档有</span>
						<span lang="EN-US">
								<font face="Times New Roman">Word</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
						<span lang="EN-US">
								<font face="Times New Roman">PDF</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
						<span lang="EN-US">
								<font face="Times New Roman">CHM</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">三种版本，检索极为方便。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 20pt">
				<font size="4">
						<span lang="EN-US" style="FONT-FAMILY: 'Wingdings 2'; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">
								<span style="mso-char-type: symbol; mso-symbol-font-family: 'Wingdings 2'">—</span>
						</span>
						<span lang="EN-US">
								<font face="Times New Roman">
								</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">它是免费的。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 20pt">
				<font size="4">
						<span lang="EN-US">
								<font face="Times New Roman">NASM</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">安装起来也很简单，在</span>
						<span lang="EN-US">
								<font face="Times New Roman">http://nasm.sourceforge.net/</font>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以找到各个平台下的安装包和相关文档。</span>
				</font>
		</p>
		<!-- page -->
<img src ="http://www.cppblog.com/mydriverc/aggbug/40634.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2008-01-07 17:37 <a href="http://www.cppblog.com/mydriverc/archive/2008/01/07/40634.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>nasm下载地址</title><link>http://www.cppblog.com/mydriverc/archive/2008/01/07/40633.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Mon, 07 Jan 2008 09:21:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/archive/2008/01/07/40633.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/40633.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/archive/2008/01/07/40633.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/40633.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/40633.html</trackback:ping><description><![CDATA[
		<a href="http://nasm.sourceforge.net/">http://nasm.sourceforge.net/</a>
<img src ="http://www.cppblog.com/mydriverc/aggbug/40633.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2008-01-07 17:21 <a href="http://www.cppblog.com/mydriverc/archive/2008/01/07/40633.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>动手编写自己的操作系统——环境设置</title><link>http://www.cppblog.com/mydriverc/archive/2008/01/07/40628.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Mon, 07 Jan 2008 08:32:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/archive/2008/01/07/40628.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/40628.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/archive/2008/01/07/40628.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/40628.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/40628.html</trackback:ping><description><![CDATA[
		<p>在现有的WindowXP2操作系统下，需要安装的软件列表：</p>
		<p>1、VMware4.5</p>
		<p>      host与guest操作系统的共享首先需要安装VMware Tools，步骤如下：1）在启动虚拟机进入<strong>文本模式(否则安装会失败)</strong>以后，鼠标依次单击VMware主界面上的“设定”选单→“VMware工具安装”选单项，然后在弹出的对话框里单击“Install”；[2）在该对话框上选中“DVD/CD-ROM（IDE 1:0）”列表项，可以看到虚拟机光驱有两种连接方式，一种是直接使用物理驱动器，另一种是使用ISO映像。这里选中后者。然后单击“浏览”按钮，指定Linux.iso映像文件的路径（位于VMware的安装目录\VMware\VMware Workstation\Programs\Linux.iso下）即可。]3）此时在/mnt[/cdrom]目录下，会发现多了一个文件：vmware-linux-tools.tar.gz，这就是VMware Tools的Linux安装包；4）然后再把该文件拷贝到tmp目录下，键入“cp ./vmware-linux-tools.tar.gz /tmp”命令即可。5）现在虚拟机光驱的使命完成了，应该把它卸载，用命令“umount /dev/cdrom”即可。6）接下来应该解压缩vmware-linux-tools.tar.gz文件。首先进入tmp目录，用“cd /tmp”命令，然后用“tar zxf vmware-linux-tools.tar.gz”命令将其解压缩，把它释放到同名目录下（即vmware-linux-tools目录）。7）然后用“cd vmware-linux-tools[或者别的名字]”进入解压后的目录，用“ls”命令显示其下的内容，从中可以看到install.pl是VMware Tools的安装程序。8）最后用“./install.pl[可能是别的文件名]”命令来运行该安装程序，然后根据屏幕提示一路回车。到此整个安装过程算是完成了。</p>
		<p>      设置文件共享(必须先安装好VMware Tools)：VM——〉setting——〉Options——〉Shared Folders，linux中对应的目录为：/mnt/hgfs</p>
		<p>      添加启动虚拟软驱：启动虚拟机之前——〉VM——〉setting——〉Hardware——〉如果device选项中没有Floppy的话，“add”——〉create a blank floppy or use a  floppy: *.img——〉</p>
		<p>2、Linux9.0 </p>
		<p>3、WinImage8.0：创建虚拟软驱*.img文件</p>
		<p>4、FloppyWriter：将*.bin文件写入*.img文件的工具</p>
		<p>5、asm汇编编译、调试工具</p>
		<p>nasm：<a href="http://webster.cs.ucr.edu/AsmTools/NASM/index.html"><font color="#4a6668">http://webster.cs.ucr.edu/AsmTools/NASM/index.html</font></a></p>
		<p>nasm manual：<a href="http://nasm.sourceforge.net/doc/html/nasmdoc0.html"><font color="#4a6668">http://nasm.sourceforge.net/doc/html/nasmdoc0.html</font></a></p>
		<p>ald(需要搜索)：<a href="http://sourceforge.net/project/showfiles.php?group_id=102112"><font color="#4a6668">http://sourceforge.net/project/showfiles.php?group_id=102112</font></a>，安装这个软件运行./configure的时候，因为要修改文件夹的读写属性，如果没有足够的权限或者是运行在与host共享的文件夹(该文件夹一般不允许修改读写属性，但是可以读写文件)下，则会报告“<strong>chmod</strong> …… "710" "700" permited”类似的错误。</p>
		<p>gdb的图形版本ddd：<a href="http://www.gnu.com/ddd"><font color="#4a6668">www.gnu.com/ddd</font></a></p>
		<p>6、安装virtualpc和PC-DOS/MS-DOS——没有必要装微软的这个破东西，在VMware中也可以和硬盘共享</p>
		<p>到microsoft主页上下载virtual pc2004(热键为键盘右边的Alt)：<a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=6D58729D-DFA8-40BF-AFAF-20BCB7F01CD1&amp;displaylang=en"><font color="#4a6668">http://www.microsoft.com/downloads/details.aspx?FamilyId=6D58729D-DFA8-40BF-AFAF-20BCB7F01CD1&amp;displaylang=en</font></a></p>
		<p>dos启动盘下载地址：<a href="http://www.cn-dos.net/newdos/doswarea.htm#pcdos"><font color="#4a6668">http://www.cn-dos.net/newdos/doswarea.htm#pcdos</font></a></p>
		<p>共享设置，网络上盛传的文件夹共享方法我总是不能成功，大概是没有权限写。这里有另外一种办法可以访问到所有的硬盘信息，只是不能写，但是足矣。主机上写asm程序，dos虚拟机上运行实模式下的com程序。</p>
		<p>新建一个MS-DOS的虚拟机——〉新建一个虚拟的hard disk——〉完成之后，点击此虚拟机的setting——〉在hard Disk1中，运行Virtual Disk向导——〉创建一个新的Virtual Disk——〉在Virtual Hard Disk Option选项中选择“Linked to a hard disk”——〉返回到此虚拟机的setting中的Hard Disk 1，将刚刚新建的Virtual Disk加载到Hard Disk 1中去——〉运行此虚拟机，点击菜单栏的Floppy中的“Capture Floppy Disk Img”，加载下载的MS-DOS/PC-DOS img文件。</p>
		<p>7、Virtual PC中启动Turbo debugger(<font color="#ff0000">tasm5</font>中包含此软件)</p>
		<p>下载地址：<a href="http://www.begin.org.cn/"><font color="#4a6668">http://www.begin.org.cn/</font></a></p>
		<p>正式版3.0（推荐）：<a href="http://tt.stu.edu.cn/download/Application.htm"><font color="#4a6668">http://tt.stu.edu.cn/download/Application.htm</font></a></p>
		<p>虽然在6中说到不能在与主机共享的文件夹中进行写操作，但是是可以在虚拟软驱中写文件的，所以在VPC的dos中可以将程序安装在A盘中。安装鼠标驱动也是这么实现的，先用WinImage将鼠标驱动程序加载到dos驱动程序中去，再在A盘中直接进行安装</p>
<img src ="http://www.cppblog.com/mydriverc/aggbug/40628.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2008-01-07 16:32 <a href="http://www.cppblog.com/mydriverc/archive/2008/01/07/40628.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编写自己的操作系统 转</title><link>http://www.cppblog.com/mydriverc/archive/2008/01/07/40627.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Mon, 07 Jan 2008 08:28:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/archive/2008/01/07/40627.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/40627.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/archive/2008/01/07/40627.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/40627.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/40627.html</trackback:ping><description><![CDATA[
		<h2 class="diaryTitle">编写自己的操作系统- -</h2>
		<p>                                       </p>
		<p>
		</p>
		<p>看看吧!很不错的!</p>
		<p>自由软件社区是一个充满自由和梦想的地方，在10余年的时间里它创造了一个又一个奇迹。然而，这些奇迹的创造者不只是Stallman，也不只是Linus Torvalds，而是活跃在世界各地的不计其数的开发人员。 </p>
		<br />
		<p>作者：伊梅</p>
		<p>自由软件社区是一个充满自由和梦想的地方，在10余年的时间里它创造了一个又一个奇迹。然而，这些奇迹的创造者不只是Stallman，也不只是Linus Torvalds，而是活跃在世界各地的不计其数的开发人员。 <br /><br />在使用各种功能强大的自由软件时，我总会对其开发 </p>
		<table cellspacing="0" cellpadding="0" align="left" border="0">
				<tbody>
						<tr>
								<td>
										<span>
										</span>
								</td>
						</tr>
				</tbody>
		</table>者充满崇敬之情，期盼有朝一日自己也能成为他们中的一员。很多对自由社区充满向往之情的人，虽然也想努力融身于其中，但又不知该怎么做。那么，就请与我们一起从编写一个简单的操作系统开始吧！ <br /><br /><br />我们要做的事情 <br /><br /><br />有人可能担心自己既没有学过计算机原理，也没有学过操作系统原理，更不懂汇编语言，对C语言也一知半解，能写操作系统吗？答案是没问题。我将带大家一步一步完成自己的操作系统。当然如果学一学上述内容再好不过。 <br /><br />首先要明确处理器(也就是CPU)控制着计算机。对PC而言，启动的时候，CPU都处在实模式状态，相当于只是一个Intel 8086处理器。也就是说，即使你现在拥有一个奔腾处理器，它的功能也只能是8086级别。从这一点上来讲，可以使用一些软件把处理器转换到著名的保护模式。只有这样，我们才可以充分利用处理器的强大功能。 <br /><br />编写操作系统开始是对BIOS控制，取出存储在ROM里的程序。BIOS是用来执行POST(Power On Self Test，自检)的。自检是检查计算机的完整性(比如外设是否工作正常、键盘是否连接等)。这一切完成以后，你就会听到PC喇叭发出一声清脆的响声。如果一切正常，BIOS就会选择一个启动设备，并且读取该设备的第一扇区(即启动扇区)，然后控制过程就会转移到指定位置。启动设备可能是一个软盘、光盘、硬盘，或者其它所选择的设备。在此我们把软盘作为启动设备。如果我们已经在软盘的启动扇区里写了一些代码，这时它就被执行。因此，我们的目的很明确，就是往软盘的启动扇区写一些程序。 <br /><br />首先使用8086汇编来写一个小程序，然后将其拷贝至软盘的启动扇区。为了实现拷贝，要写一个C程序。最后，使用软盘启动计算机。 <br /><br /><br />需要的工具 <br /><br /><br />● as86：这是一个汇编程序，它负责把写的代码转换成目标文件。 <br /><br />● ld86：这是一个连接器，as86产生的目标代码由它来转换成真正的机器语言。机器语言是8086能够解读的形式。 <br /><br />● GCC：著名的C编程器。因为我们需要写一个C程序将自己的OS转移到软盘中。 <br /><br />● 一张空软盘：它用于存储编写的操作系统，也是启动设备。 <br /><br />● 一台装有Linux的计算机：这台机器可以很旧，386、486都可以。 <br /><br />在大部分标准Linux发行版中都会带有as86和ld86。在我使用的Red Hat 7.3中就包含有这两个工具，并且在默认的情况下，它已经安装在机器里。如果使用的Linux没有这两个工具，可以从网上下载(http: //www.cix.co.uk/~mayday/)，这两个工具都包含在一个名为bin86的软件包中。此外，有关的文档也可以在网上获得 (www.linux.org/docs/ldp/howto/Assembly-HOWTO/as86.html)。 <br /><br /><br />开始工作 <br /><br /><br />使用一个你喜欢的编辑器输入以下内容： <br /><br />entry start <br />start: <br />mov ax,#0xb800 <br />mov es,ax <br />seg es <br />mov [0],#0x41 <br />seg es <br />mov [1],#0x1f <br />loop1: jmp loop1 <br /><br /><br />这是as86可以读懂的一段汇编程序。第一个句子指明了程序的入口点，声明整个过程从start处开始。第二行指明了start的位置，说明整个程序要从start处开始执行。0xb800是显存的开始地址。#表明其后是一个立即数。执行语句： <br /><br />mov ax,#oxb800 <br /><br /><br />ax 寄存器的值就变为0xb800，这就是显存的地址。下面再将这个值移至es寄存器，es是附加段寄存器。请记住8086有一个分段的体系结构。它的各段寄存器为代码段、数据段、堆栈段和附加段，对应的寄存器名称分别为cs、ds、ss和es。事实上，我们把显存地址送入了附加段，因此，任何送入附加段的东西都会被送到显存中。 <br /><br />要在屏幕上显示字符，就需要向显存中写两个字节。前一个是所要显示字符的ASCⅡ值，第二个字节表示该字符的属性。属性包括字符的前景色、背景色及是否闪烁等等。seg es指明下一个将要执行的指令是指向es段的。所以，我们把值0x41(在ASCⅡ中表示的字符是A)送到显存的第一个字节中。接下来要把字符的属性送到下一个字节当中。在此输入的是0x1f，该属性指的是在蓝色背景下显示白色的字符。因此，如果执行这个程序，就可以在屏幕上得到显示在蓝底上的一个白色的 A。接着是一个循环。因为在执行完显示字符的任务后，要么让程序结束，要么使用一个循环使其永远运行下去。把该文件命名为boot.s，然后存盘。 <br /><br />此处显存的概念说得不是很清楚，有必要进一步解释一下。假设屏幕由80列×25行组成，那么第一行就需要160字节，其中一个字节用于表示字符，另外一个字节用于表示字符的属性。如果要在第三行显示某一字符的话，就要跳过显存的第0和1字节(它们是用于显示第1列的)，第2和3字节(它们是用于显示第2列的)，然后把需要显示字符的ASCⅡ码值入第4字节，把字符的属性写入第5字节。 <br /><br /><br />把程序写至启动扇区 <br /><br /><br />下面写一个C程序，把我的操作系统写入软盘第一扇区。程序内容如下： <br /><br />#include /* unistd.h 需要这个文件 */ <br />#include /* 包含有read和write函数 */ <br />#include <br />int main() <br />{ <br />char boot_buf[512]; <br />int floppy_desc, file_desc; <br />file_desc = open("./boot", O_RDONLY); <br />read(file_desc, boot_buf, 510); <br />close(file_desc); <br />boot_buf[510] = 0x55; <br />boot_buf[511] = 0xaa; <br />floppy_desc = open("/dev/fd0", O_RDWR); <br />lseek(floppy_desc, 0, SEEK_CUR); <br />write(floppy_desc, boot_buf, 512); <br />close(floppy_desc); <br />} <br /><br /><br />首先，以只读模式打开boot文件，然后在打开文件时把文件描述符复制到file_desc变量中。从文件中读取510个字符，或者读取直到文件结束。在本例中由于文件很小，所以是读取至文件结束。然后关闭文件。 <br /><br />最后4行代码打开软盘驱动设备(一般来说是/dev/fd0)。使用lseek找到文件开始处，然后从缓冲中向软盘写512个字节。 <br /><br />在read、write、open和lseek的帮助页中，可以看到与函数所有有关的参数及其使用方法。程序中有两行比较难懂： <br /><br />boot_buf[510] = 0x55; <br />boot_buf[511] = 0xaa; <br /><br /><br />该信息是用于BIOS的，如果它识别出该设备是一个可启动的设备，那么在第510和511的位置，该值就应该是0x55和0xaa。程序会把文件boot读至名为boot_buf的缓冲中。它要求改变第510和第511字节，然后把boot_buf写至软盘之上。如果执行代码，软盘上的前512字节就包含了启动代码。最后，把文件存为write.c。 <br /><br /><br />编译运行 <br /><br /><br />使用下面的命令把文件变为可执行文件： <br /><br />as86 boot.s -o boot.o <br />ld86 -d boot.o -o boot <br />cc write.c -o write <br /><br /><br />首先将boot.s文件编译成目标文件boot.o，然后将该文件连接成最终的boot文件。最后C程序编译成可执行的write文件。 <br /><br />插入一个空白软盘，运行以下程序： <br /><br />./write <br /><br /><br />重新启动电脑，进行BIOS的界面设置，并且把软盘设为第一个启动的设备。然后插入软盘，电脑从软盘上启动。 <br /><br />启动完成后，在屏幕上可以看到一个字母A(蓝底白字)，启动速度很快，几乎是在瞬间完成。这就意味着系统已经从我们制作的软盘上启动了，并且执行了刚才写入启动扇区的程序。现在，它正处在一个无限循环的状态。所以，如果想进入Linux，必需拿掉软盘，并且重启机器。 <br /><br />至此，这个操作系统就算完成了，虽然它没有实现什么功能，但是它已经可以启动机器了。 <br /><br />下一期我将在这个启动扇区程序里加入一些代码，使它可以做一些比较复杂的事情(比如使用BIOS中断、保护模式切换等等)。 <br /><br />自己动手写操作系统(二) <br />作者：伊梅 <br /><br />上一期，我讲述了如何在软盘的启动扇区写一些代码，然后再从软盘启动的过程。制作好一个启动扇区，在切换到保护模式之前，我们还应该知道如何使用BIOS中断。BIOS中断是一些由BIOS提供的、为了使操作系统的创建更容易的低级程序。在本文中，我们将学习处理BIOS的中断。 <br /><br />为什么要用BIOS <br /><br />BIOS 会把启动扇区拷贝至RAM中，并且执行这些代码。除此之外，BIOS还要做很多其它的事情。当一个操作系统刚开始启动时，系统中并没有显卡驱动、软盘驱动等任何驱动程序。因此，启动扇区中不可能包含任何一个驱动程序，我们要采取其它的途径。这个时候，BIOS就可以帮助我们了。BIOS中包含有各种可以使用的程序，包括检测安装的设备、控制打印机、计算内存大小等用于各种目的的程序。这些程序就是所说的BIOS中断。 <br /><br />如何调用BIOS中断 <br /><br />在一般的程序设计语言中，函数的调用是一件非常容易的事情。比如在C语言中，如果有一个名为display的程序，它带有两个参数，其中参数 noofchar表示显示的字符数，参数attr表示显示字符的属性。那么要调用它，只需给出程序的名称即可。对于中断的调用，我们使用的是汇编语言中的 int指令。 <br /><br />比如，在C语言中要显示一些东西时，使用的指令如下所示： <br /><br />display(nofchar，attr)； <br />而使用BIOS时，要实现相同功能使用的指令如下： <br /><br />int 0x10 <br /><br />如何传递参数 <br /><br />在调用BIOS中断之前，我们需要先往寄存器中送一些特定的值。假设要使用BIOS的中断13h，该中断的功能是把数据从软盘传送至内存之中。在调用该中断之前，要先指定拷贝数据的段地址，指定驱动器号、磁道号、扇区号，以及要传送的扇区数等等。然后，就要往相应的寄存器送入相应的值。在进行下面的步骤前，读者有必要对这一点有比较明确地认识。 <br /><br />此外，一个比较重要的事实是同一个中断往往可以实现各种不同的功能。中断所实现的确切功能取决于所选择的功能号，功能号一般都存在ah寄存器之中。比如中断13h可以用于读磁盘、写磁盘等功能，如果把3送入ah寄存器中，那么中断选择的功能就是写磁盘；如果把2送入ah寄存器中，选择的功能则是读磁盘等。 <br /><br />我们要做的事情 <br /><br />这次我们的源代码由两个汇编语言程序和一个C程序组成。第一个汇编文件是引导扇区的代码。在引导扇区中，我们写的代码是要把软盘中第二扇区拷贝至内存段的0x500处(地址是0x5000，即偏移地址为0)。这时我们需要使用BIOS的中断13h。这时启动扇区的代码就会把控制权转移至0x500处。在第二个汇编文件中，代码会使用BIOS中断 10h在屏幕上显示一个信息。C程序实现的功能则是把可执行的文件1拷贝至启动扇区，把可执行的文件2拷贝至软盘的第二扇区。 <br /><br />启动扇区代码 <br /><br />使用中断13h，启动扇区把软盘第二扇区里的内容加载至内存的0x5000处(段地址为0x500)。下面的代码是用于实现这一目的的代码，将其保存至文件sbect.s中。 <br /><br />LOC1=0x500 <br />entry start <br />start: <br />mov ax,#LOC1 <br />mov es,ax <br />mov bx,#0 <br />mov dl,#0 <br />mov dh,#0 <br />mov ch,#0 <br />mov cl,#2 <br />mov al,#1 <br />mov ah,#2 <br />int 0x13 <br />jmpi 0,#LOC1 <br /><br /><br />上面代码第一行类似于一个宏。接下去的两行则是把值0x500加载至es寄存器中，这是软盘上第二扇区代码将拷贝到的地方(第一扇区是启动扇区)。这时，把段内的偏移设为0。 <br /><br />接下来把驱动器号送入dl寄存器中，其中磁头号送入dl寄存器中，磁道号送入ch寄存器中，扇区号送入cl寄存器中，扇区数送入al寄存器之中。我们想要实现的功能是把扇区2、磁道号为0、驱动器号为0的内容送至段地址0x500处。所有这些参数都和1.44MB的软盘相对应。 <br /><br />把2送入ah寄存器中，是选择了由中断13h提供的相应功能，即实现从软驱转移数据的功能。 <br /><br />最后调用中断13h，并且转至偏移为0的段地址0x500处。 <br /><br />第二个扇区的代码 <br /><br />第二个扇区中的代码如下所示(把这些代码保存至文件sbect2.s之中)： <br /><br />entry start <br />start: <br />mov ah,#0x03 <br />xor bh,bh <br />int 0x10 <br /><br />mov cx,#26 <br />mov bx,#0x0007 <br />mov bp,#mymsg <br />mov ax,#0x1301 <br />int 0x10 <br /><br />loop1: jmp loop1 <br />mymsg: <br />.byte 13,10 <br />.ascii "Operating System is Loading......" <br /><br /><br />上面代码将被加载至段地址为0x500处，并且被执行。在这段代码中，使用了中断10h来获取目前的光标位置，然后显示信息。 <br /><br />从第3行到第5行用于得到目前光标的位置，在此中断10h选用的是功能3。然后，清除了bh寄存器的内容，并把字符串送至ch寄存器中。在bx中，我们送入了页码及显示的属性。此处，我们想要在黑背景上显示白色的字符。然后，把要显示字符的地址送到bp之中，信息由两个字节组成，其值分别为13的10，它们分别对应回车和LF(换行)的ASCⅡ值。接下来是一个由29个字符组成的串；在下面实现的功能是输出字符串然后移动光标；最后是调用中断，然后进入循环。 <br /><br />C程序代码 <br />C程序的源代码如下所示，将其存储为write.c文件。 <br /><br />#include /* unistd.h needs this */ <br />#include /* contains read/write */ <br />#include <br />int main() <br />{ <br />char boot_buf[512]; <br />int floppy_desc, file_desc; <br />file_desc = open("./bsect", O_RDONLY); <br />read(file_desc, boot_buf, 510); <br />close(file_desc); <br />boot_buf[510] = 0x55; <br />boot_buf[511] = 0xaa; <br />floppy_desc = open("/dev/fd0", O_RDWR); <br />lseek(floppy_desc, 0, SEEK_SET); <br />write(floppy_desc, boot_buf, 512); <br />file_desc = open("./sect2", O_RDONLY); <br />read(file_desc, boot_buf, 512); <br />close(file_desc); <br />lseek(floppy_desc, 512, SEEK_SET); <br />write(floppy_desc, boot_buf, 512); <br />close(floppy_desc); <br />} <br /><br /><br />在上一期中，我曾经介绍过如何操作能启动的软盘。现在这一个过程稍微有点不同，首先把由bsect.s编译出来的可执行文件bsect拷贝至软盘的启动扇区。然后再把由sect2.s产生的可执行文件sect2拷贝至软盘的第二个扇区。 <br /><br />把上述文件置于同一目录之下，然后分别对其进行编译，方法如下所示： <br /><br />as86 bsect.s -o bsect.o <br />ld86 -d bsect.o -o bsect <br /><br />对sect2.s文件重复以上的操作，得出可执行文件sect2。编译write.c，插入软盘后执行write文件，命令如下所示： <br /><br />cc write.c -o write <br />./write <br /><br />下一步我们要做的事情 <br /><br />从软盘启动以后，可以看到显示出来的字符串。这是使用了BIOS中断来完成的。下一期要做的事情是在这个操作系统中实现实模式向保护模式的转换。 <br /><br />自己动手写操作系统(三) <br />作者：伊梅 <br /><br /><br />在上两期中（自己动手写操作系统1，2），我向大家讲述了如何使用Linux 提供的开发工具在软盘的启动扇区写一些代码，以及如何调用BIOS的问题。现在，这个操作系统已经越来越接近当年Linus Torvalds的那个具有"历史意义"的Linux内核了。因此，要马上把这个系统切换到保护模式之下。 <br /><br />什么是保护模式 <br /><br />自从1969年推出第一个微处理器以来，Intel处理器就在不断地更新换代，从8086、8088、80286，到80386、80486、奔腾、奔腾 Ⅱ、奔腾4等，其体系结构也在不断变化。80386以后，提供了一些新的功能，弥补了8086的一些缺陷。这其中包括内存保护、多任务及使用640KB以上的内存等，并仍然保持和8086家族的兼容性。也就是说80386仍然具备了8086和80286的所有功能，但是在功能上有了很大的增强。早期的处理器是工作在实模式之下的，80286以后引入了保护模式，而在80386以后保护模式又进行了很大的改进。在80386中，保护模式为程序员提供了更好的保护，提供了更多的内存。事实上，保护模式的目的不是为了保护程序，而是要保护程序以外的所有程序（包括操作系统）。 <br /><br />简言之，保护模式是处理器的一种最自然的模式。在这种模式下，处理器的所有指令及体系结构的所有特色都是可用的，并且能够达到最高的性能。 <br /><br />保护模式和实模式 <br /><br />从表面上看，保护模式和实模式并没有太大的区别，二者都使用了内存段、中断和设备驱动来处理硬件，但二者有很多不同之处。我们知道，在实模式中内存被划分成段，每个段的大小为64KB，而这样的段地址可以用16位来表示。内存段的处理是通过和段寄存器相关联的内部机制来处理的，这些段寄存器（CS、DS、 SS和ES）的内容形成了物理地址的一部分。具体来说，最终的物理地址是由16位的段地址和16位的段内偏移地址组成的。用公式表示为： <br /><br />物理地址=左移4位的段地址+偏移地址。 <br /><br />在保护模式下，段是通过一系列被称之为"描述符表"的表所定义的。段寄存器存储的是指向这些表的指针。用于定义内存段的表有两种：全局描述符表(GDT)和局部描述符表(LDT)。GDT是一个段描述符数组，其中包含所有应用程序都可以使用的基本描述符。在实模式中，段长是固定的(为64KB)，而在保护模式中，段长是可变的，其最大可达4GB。LDT也是段描述符的一个数组。与GDT不同，LDT是一个段，其中存放的是局部的、不需要全局共享的段描述符。每一个操作系统都必须定义一个GDT，而每一个正在运行的任务都会有一个相应的LDT。每一个描述符的长度是8个字节，格式如图3所示。当段寄存器被加载的时候，段基地址就会从相应的表入口获得。描述符的内容会被存储在一个程序员不可见的影像寄存器(shadow register)之中，以便下一次同一个段可以使用该信息而不用每次都到表中提取。物理地址由16位或者32位的偏移加上影像寄存器中的基址组成。实模式和保护模式的不同可以从图1和图2中很清楚地看出来。 <br /><br /><br />图1 实模式的寻址 <br /><br /><br />图2 保护模式下的寻址 <br /><br /><br />图3 段描述俯的格式 <br /><br />此外，还有一个中断描述符表(IDT)。这些中断描述符会告诉处理器到那里可以找到中断处理程序。和实模式一样，每一个中断都有一个入口，但是这些入口的格式却完全不同。因为在切换到保护模式的过程中没有使用到IDT，所以在此就不多做介绍了。 <br /><br />进入保护模式 <br /><br />80386 有4个32位控制寄存器，名字分别为CR0、CR1、CR2和CR3。CR1是保留在未来处理器中使用的，在80386中没有定义。CR0包含系统的控制标志，用于控制处理器的操作模式和状态。CR2和CR3是用于控制分页机制的。在此，我们关注的是CR0寄存器的PE位控制，它负责实模式和保护模式之间的切换。当PE=1时，说明处理器运行于保护模式之下，其采用的段机制和前面所述的相应内容对应。如果PE=0，那么处理器就工作在实模式之下。 <br /><br />切换到保护模式，实际就是把PE位置为1。为了把系统切换到保护模式，还要做一些其它的事情。程序必须要对系统的段寄存器和控制寄存器进行初始化。把PE位置1后，还要执行跳转指令。过程简述如下： <br /><br />1.创建GDT表; <br /><br />2.通过置PE位为1进入保护模式; <br /><br />3.执行跳转以清除在实模式下读取的任何指令。 <br /><br />下面使用代码来实现这个切换过程。 <br /><br />需要的东西 <br /><br />◆ 一张空白软盘 <br /><br />◆ NASM编译器 <br /><br />下面是整个程序的源代码： <br /><br />org 0x07c00; 起始地址是0000:7c00 <br />jmp short begin_boot ; 跳过其它的数据，跳转到引导程序的开始处 <br />bootmesg db "Our OS boot sector loading ......" <br />pm_mesg db "Switching to protected mode ...." <br />dw 512 ; 每一扇区的字节数 <br />db 1 ; 每一簇的扇区数 <br />dw 1 ; 保留的扇区号 <br />db 2 <br />dw 0x00e0 <br />dw 0x0b40 <br />db 0x0f0 <br />dw 9 <br />dw 18 <br />dw 2 ; 读写扇区号 <br />dw 0 ; 隐藏扇区号 <br />print_mesg : <br />mov ah,0x13 ; 使用中断10h的功能13，在屏幕上写一个字符串 <br />mov al,0x00 ; 决定调用函数后光标所处的位置 <br />mov bx,0x0007 ; 设置显示属性 <br />mov cx,0x20 ; 在此字符串长度为32 <br />mov dx,0x0000 ; 光标的起始行和列 <br />int 0x10 ; 调用BIOS的中断10h <br />ret ; 返回调用程序 <br />get_key : <br />mov ah,0x00 <br />int 0x16 ; Get_key使用中断16h的功能0，读取下一个字符 <br />ret <br />clrscr : <br />mov ax,0x0600 ; 使用中断10h的功能6，实现卷屏，如果al=0则清屏 <br />mov cx,0x0000 ; 清屏 <br />mov dx,0x174f ; 卷屏至23，79 <br />mov bh,0 ; 使用颜色0来填充 <br />int 0x10 ; 调用10h中断 <br />ret <br />begin_boot : <br />call clrscr ; 先清屏 <br />mov bp,bootmesg ; 提供串地址 <br />call print_mesg ; 输出信息 <br />call get_key ; 等待用户按下任一键 <br />bits 16 <br />call clrscr ; 清屏 <br />mov ax,0xb800 ; 使gs指向显示内存 <br />mov gs,ax ; 在实模式下显示一个棕色的A <br />mov word [gs:0],0x641 ; 显示 <br />call get_key ; 调用Get_key等待用户按下任一键 <br />mov bp,pm_mesg ; 设置串指针 <br />call print_mesg ; 调用print_mesg子程序 <br />call get_key ; 等待按键 <br />call clrscr ; 清屏 <br />cli ; 关中断 <br />lgdt[gdtr] ; 加载GDT <br />mov eax,cr0 <br />or al,0x01 ; 设置保护模式位 <br />mov cr0,eax ; 将更改后的字送至控制寄存器中 <br />jmp codesel:go_pm <br />bits 32 <br />go_pm : <br />mov ax,datasel <br />mov ds,ax ; 初始化ds和es，使其指向数据段 <br />mov es,ax <br />mov ax,videosel ; 初始化gs，使其指向显示内存 <br />mov gs,ax <br />mov word [gs:0],0x741 ; 在保护模式下显示一个白色的字符A <br />spin : jmp spin ; 循环 <br />bits 16 <br />gdtr : <br />dw gdt_end-gdt-1 ; gdt的长度 <br />dd gdt ; gdt的物理地址 <br />gdt <br />nullsel equ $-gdt ; $指向当前位置，所以nullsel = 0h <br />gdt0 ; 空描述符 <br />dd 0 <br />dd 0 ; 所有的段描述符都是64位的 <br />codesel equ $-gdt ; 这是8h也就是gdt的第二个描述符 <br />code_gdt <br />dw 0x0ffff ; 段描述符的界限是4Gb <br />dw 0x0000 <br />db 0x00 <br />db 0x09a <br />db 0x0cf <br />db 0x00 <br />datasel equ $-gdt <br />data_gdt <br />dw 0x0ffff <br />dw 0x0000 <br />db 0x00 <br />db 0x092 <br />db 0x0cf <br />db 0x00 <br />videosel equ $-gdt <br />dw 3999 <br />dw 0x8000 ; 基址是0xb8000 <br />db 0x0b <br />db 0x92 <br />db 0x00 <br />db 0x00 <br />gdt_end <br />times 510-($-$$) db 0 <br />dw 0x0aa55 <br /><br /><br />把上面的代码存在一个名为abc.asm的文件之中，使用命令nasm abc.asm，将得出一个名为abc的文件。然后插入软盘，输入命令：dd if=abc of=/dev/fd0。该命令将把文件abc写入到软盘的第一扇区之中。然后重新启动系统，就会看到如下的信息： <br /><br />*Our os booting................ <br />* A (棕色) <br />* Switching to protected mode.... <br />* A (白色) <br /><br /><br />对代码的解释 <br /><br />上面给出了所有的代码，下面我对上述代码做一些解释。 <br /><br />◆ 使用的函数 <br /><br />下面是代码中一些函数的说明： <br /><br />print_mesg 该子程序使用了BIOS中断10h的功能13h，即向屏幕写一字符串。属性控制是通过向一些寄存器中送入不同的值来实现的。中断10h是用于各种字符串操作，我们把子功能号13h送到ah中，用于指明要打印一个字符串。al寄存器中的0说明了光标返回的起始位置，0表示调用函数后光标返回到下一行的行首。如果al为1则表示光标位于最后一个字符处。 <br /><br />显存被分成了几页，在同一时刻只能显示其中的一页。bh指明的是页号；bl则指明要显示字符的颜色；cx指明要显示字符串的长度；dx指明光标的位置(即起始的行和列)。所有相关寄存器初始化完成以后，就可以调用BIOS中断10h了。 <br /><br />get_key 使用中断16h的子功能00h，从屏幕得到下一个字符。 <br /><br />clrscr 该函数使用了中断10h的另外一个子功能06h，用于输出开始前清屏。初始化时给al中送入0。寄存器cx和dx指明要清屏的屏幕范围，在本例中是整个屏幕。寄存器bh指明屏幕填充的颜色，在本例中是黑色。 <br /><br />◆ 其它内容 <br /><br />程序一开始是一条短跳转指令，跳到begin_boot处。在实模式下，在此打印一个棕色的"A"，并且设置一个GDT。切换到保护模式，并且打印一个白色的"A"。这两种模式使用的都是自己的寻址方法。 <br /><br />在实模式下，使用段寄存器gs指示显存位置，我们使用的是CGA显卡(默认基址是0xb8000)。在代码中是不是漏了一个0呢？没有，因为实模式下会提供一个附加的0。这种方式也被80386继承下来了。A的ASCⅡ是0x41，0x06指明了需要一个棕色的字符。该显示会一直持续直至按下任意键。下面要在屏幕上显示一句话，告诉使用者下面马上要进入保护模式了。 <br /><br />启动到保护模式，在进行切换时不希望此时有中断的影响，故要关闭所有的中断(使用cli来实现)。然后对GDT初始化。在整个切换过程中，对4个描述符进行了初始化。这些描述符对代码段(code_gdt)、数据和堆栈段 (data_gdt)，以及为了访问显存而对显示段进行初始化。此外，还会对一个空描述符进行初始化。 <br /><br />GDT的基址要加载至GDTR 系统寄存器之中。gdtr段的第一个字加载的是GDT的大小，在下一个双字中则加载的是基址。然后，lgdt指令把把gdt段加载至GDTR寄存器中。现在已经做好了切换到保护模式前的所有准备。最后一件事情就是把CR0寄存器的PE位置1。不过，即使这样还没有处于保护模式状态之下。 <br /><br />设置了PE位以后，还需要通过执行JMP指令来清除处理器指令预取队列。在80386中，使用指令前总是先将其从内存中取出，并且进行解码和寻址。然而，当进入保护模式以后，预取指令信息(它还处于实地址模式)就无效了。使用JMP指令的目的就是强迫处理器放弃无效的信息。 <br /><br />现在，已经在保护模式下了。那么，如何检测是在保护模式状态之下呢？让我们来看一看屏幕上这个白色的字母A。在这里，使用了数据段选择符(datase1)对数据段和附加段进行了初始化，使用显示段选择符(videose1)对gs进行了初始化。告示的字符"A"其ASCⅡ值和属性位于[gs:0000]处，也就是 b8000:0000处。循环语句使得该字符一直在屏幕上显示，直至重新启动系统。<img src ="http://www.cppblog.com/mydriverc/aggbug/40627.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2008-01-07 16:28 <a href="http://www.cppblog.com/mydriverc/archive/2008/01/07/40627.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开发自己的操作系统引导程序 转</title><link>http://www.cppblog.com/mydriverc/archive/2008/01/07/40622.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Mon, 07 Jan 2008 08:11:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/archive/2008/01/07/40622.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/40622.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/archive/2008/01/07/40622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/40622.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/40622.html</trackback:ping><description><![CDATA[
		<strong>开发自己的操作系统引导程序</strong>
		<br />
		<br />　　当你打开计算机时发生了什么？ <br /><br />　　1.电源打开；2.BIOS开始执行；3.引导程序开始执行。 <br /><br />　　引导程序的规定：你要有一个普通的二进制文件（COM 格式）；大小是512个字节；最后两个字节一定是0AA55h；它能被载入到内存地址0x7C00。 <br /><br />　　工具： <br /><br />　　NASM——是一个免费的汇编工具（有DOS/windows/Linux三种版本） <br /><br />　　PARTCOPY2.0——DOS下可自由往磁盘拷贝数据的软件 <br /><br />　　举例： <br /><br />　　1.Just hang…… <br /><br />　　这个简单的引导程序只能挂起： <br /><br />　　hang: <br /><br />　　jmp hang <br /><br />　　times 512－(＄－＄＄)－2 db 0 <br /><br />　　dw 0AA55h <br /><br />　　连接这个引导程序： <br /><br />　　nasm －f bin －o hang.bin hang.asm <br /><br />　　现在你需要一张格式化磁盘，传送hang.bin到磁盘的引导扇区 <br /><br />　　partcopy hang.bin 0 200 －f0 <br /><br />　　“0”的意思是指从hang.bin文件的顶端开始传送 <br /><br />　　“200”的意思是指拷贝200个字节 <br /><br />　　插入磁盘和重新启动机器，测试这个引导程序。 <br /><br />　　2.一个实模式下的引导程序 <br /><br />　　上面的程序非常简单，下面介绍一个稍微复杂一点的程序。 <br /><br />　　bits 16 <br /><br />　　org 0x7C00 <br /><br />　　start: <br /><br />　　cli；关中断 <br /><br />　　mov ax,0x9000；设置堆栈址：0x90000 <br /><br />　　mov ss,ax <br /><br />　　mov sp,0 <br /><br />　　sti；开中断 <br /><br />　　l1:push ds <br /><br />　　mov dl,0； <br /><br />　　重新设置磁盘控制器 <br /><br />　　mov ax,0 <br /><br />　　int 13h <br /><br />　　pop ds <br /><br />　　jc fail <br /><br />　　push es <br /><br />　　mov ax,0x1000；ES:BX=10000 <br /><br />　　mov es,ax <br /><br />　　mov bx,0 <br /><br />　　mov ah,2；读磁盘扇区 <br /><br />　　mov al,5；读入5个扇区 <br /><br />　　mov cx,2；柱面号=0，扇区号=2 <br /><br />　　mov dx, 0；磁头号=0，驱动器号=0 <br /><br />　　int 13h；ES:BX=来自磁盘上的数据 <br /><br />　　pop es <br /><br />　　jc l1 <br /><br />　　mov ax,0x10000；设置段寄器 <br /><br />　　mov es,ax <br /><br />　　mov ds,ax <br /><br />　　push ax <br /><br />　　mov ax,0 <br /><br />　　push ax <br /><br />　　retf <br /><br />　　fail: <br /><br />　　jmp fail <br /><br />　　times 512－(＄－＄＄)－2 db 0 <br /><br />　　dw 0AA55h <br /><br />　　连接这个引导程序： <br /><br />　　nasm －f bin －o boot.bin boot.asm <br /><br />　　传送boot.bin到磁盘的引导扇区 <br /><br />　　partcopy boot.bin 0 200 －f0 <br /><br />　　为了使程序可以看到，在编译下面程序 <br /><br />　　mov ax,1000h；修改段寄存器 <br /><br />　　mov ds,ax <br /><br />　　mov es,ax <br /><br />　　mov si,msg；打印 "JIPPIKAYE!" <br /><br />　　call putstr <br /><br />　　hang:；挂起 <br /><br />　　jmp hang <br /><br />　　putstr: <br /><br />　　lodsb <br /><br />　　or al,al <br /><br />　　jz short putstrd <br /><br />　　mov ah,0x0E <br /><br />　　mov bx,0x0007 <br /><br />　　int 0x10 <br /><br />　　jmp putstr <br /><br />　　putstrd: <br /><br />　　retn <br /><br />　　msg db 'JIPPIKAYE!',13,10,0 <br /><br />　　连接和传送： <br /><br />　　nasm －f bin －o boot.bin boot.asm <br /><br />　　partcopy boot.bin 0 200 －f0 200 <br /><br />　　在partcopy中最后一个参数“200”意思是指磁盘的偏移地址插入磁盘和重新启动机器，你会看到“JIPPIKAYE”然后挂起。 <br /><br /><br /><br />本文转自 <br /><br /><a href="http://www.woos.cn/bbs/read.php?tid=72">http://www.woos.cn/bbs/read.php?tid=72</a><br /><img src ="http://www.cppblog.com/mydriverc/aggbug/40622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2008-01-07 16:11 <a href="http://www.cppblog.com/mydriverc/archive/2008/01/07/40622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>