声明:本文内容思路启发及个别信息受教于
1.LUPA(http://www.lupaworld.com/)
2.开源中国社区(http://oss.org.cn/)
3.Linuxsir 论坛(http://www.linuxsir.org/bbs/)
4.纯C论坛 (http://purec.hit.edu.cn/index.php)
5.Operating System resource certer(http://www.nondot.org/sabre/os/articles)
现在我在尽我所能剖析上一次的代码,并将重要信息穿插起来
1. org 0x7c00h
这里大多的解释是程序启动的入口地址,是规定,协议,即是BIOS在找到某一引导设备时会将其设备的第一个扇区的512B数 据载入到OX7c00为起点的位置处,即BIOS移交权限后开始运行的起点。
注意0x7c00为内存地址,512B为引导设备如硬盘的第一个扇区的512B的数据。
然而大家可以试一下,其实就算我们把第一行去掉,这段程序被加载的地方仍然是0x7c00h,就是说,BIOS必然会将之加载到此地址的。那么这条指令是什么意思呢?基址!大家可以注意以下调试的地址可以发现,如果没有这条指令,那么,后面算物理地址的基址为0x0000h,有这条指令的基址为0xc000h。原来这条指令是指明段基址的!
2. mov ax,cs
3. mov ds,ax
4. mov es,ax
以上三行为设置数据段,即解决如何访问段中的数据,通过地址。而地址=段地址+偏移地址。
mov ax,cs将代码段的地址移送ax ;mov ds,ax 将代码段地址移送数据段;mov es,ax 移送es附加段。
5. call PrintStr;调用PrintStr,下面介绍。
6. jmp $ ;$本身代表当前地址寄存器的值,而地址寄存器为用来保证正在汇编的指令和变量的地址偏移。所以说,本条指令的含义是,本地跳--空转--等待,目的是延长试验效果时间,是实验代码。
7. PrintSrc : ;标号,与第5段对应
8. mov ax,Hello ;将Hello变量的地址即Hello变量的内容的指针移送ax
9. mov bp,ax ;再将Hello的变量地址移送给bp。送给bp的原因是,由于bp为基指针寄存器,可以直接读取堆栈数据,因此,es与bp结合为Hello的读取地址ES:BP
10. mov cx,11 ;由于cx为计数寄存器,这说明Hello内容的长度为11个字节。否则,小了不能完全显示,大输出空格。
11. mov ax,01301h
12. mov bx,000ch
这两行是10h中断的配置,具体不同位的含义,请查看10号中断
13. int 10h ;开启10号中断。作用是显示服务(显示器)
14. ret ;PrintSrc子程序返回
15. Hello:db "My first OS" ;定义Hello字符串变量
16. time 510-($-$$) db 0 ;$是当前正在编译的指令或变量的地址,$$便是所在本节的首地址,所以,$-$为以上程序共占多大空间。我们还记得,第一节说引导区的大小必为512B,现在用512B-($-$$)=要需要多少空间可达到512B,并全部添’0‘。
好了,虽然代码段,但是要透过代码看本质,看看代码下面隐含的东西有多美妙。