用汇编写软盘引导程序

; hello-os

; TAB=4

; 以下这段是标准FAT12格式软盘专用的代码
DB 0xeb, 0x4e, 0x90
DB "HELLOIPL" ; 启动区的名称可以是任意的字符串(8字节)
DW 512 ; 每个扇区(sector)的大小(必须为512字节)
DB 1 ; 簇(cluster)的大小(必须为1个扇区)
DW 1 ; FAT的起始位置(一般从第一个扇区开始)
DB 2 ; FAT的个数(必须为2)
DW 224 ; 根目录的大小(一般设成224项)
DW 2880 ; 该磁盘的大小(必须是2880扇区)
DB 0xf0 ; 磁盘的种类(必须是0xf0)
DW 9 ; FAT的长度(必须是9扇区)
DW 18 ; 1个磁道(track)有几个扇区(必须是18)
DW 2 ; 磁头数(必须是2)
DD 0 ; 不使用分区,必须是0
DD 2880 ; 重写一次磁盘大小
DB 0,0,0x29 ; 意义不明,固定
DD 0xffffffff ;(可能是)卷标号码
DB "HELLO-OS " ; 磁盘的名称(11字节)
DB "FAT12 " ; 磁盘格式名称(8字节)
RESB 18 ; 先空出18字节
; 程序主体
DB 0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c
DB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a
DB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09
DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb
DB 0xee, 0xf4, 0xeb, 0xfd
; 信息显示部分
DB 0x0a, 0x0a ; 2个换行
DB "hello, world"
DB 0x0a ; 换行
DB 0
RESB 0x1fe-$ ; 填写0x00,直到 0x001fe
DB 0x55, 0xaa
; 以下是启动区以外部分的输出
DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
RESB 4600
DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
RESB 1469432

第二种写法:

DB 0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4f
DB 0x49, 0x50, 0x4c, 0x00, 0x02, 0x01, 0x01, 0x00
DB 0x02, 0xe0, 0x00, 0x40, 0x0b, 0xf0, 0x09, 0x00
DB 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
DB 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x29, 0xff
DB 0xff, 0xff, 0xff, 0x48, 0x45, 0x4c, 0x4c, 0x4f
DB 0x2d, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x46, 0x41
DB 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00
RESB 16
DB 0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c
DB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a
DB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09
DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb
DB 0xee, 0xf4, 0xeb, 0xfd, 0x0a, 0x0a, 0x68, 0x65
DB 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72
DB 0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00
RESB 368
DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
RESB 4600
DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
RESB 1469432


■■■■■
这里有几点新内容,我们逐一来看一下。首先是“;”命令,这是个注释命令,相当于C语言
或是C++中的“//”。正是因为有它,我们才可以在源代码里加入很多注释。
其次是DB指令的新用法。我们居然可以直接用它写字符串。在写字符串的时候,汇编语言
会自动地查找字符串中每一个字符所对应的编码,然后把它们一个字节一个字节地排列起来。
这个功能非常方便,也就是说,当我们想要变更输出信息的时候,就再也不用自己去查字符编码
表了。
26 …… 第1 天:从计算机结构到汇编程序入门
再有就是DW指令和DD指令,它们分别是“data word”和“data double-word”的缩写,是
DB指令的“堂兄弟”。word的本意是“单词”,但在计算机汇编语言的世界里,word指的是“16
位”的意思,也就是2个字节。“double-word”是“32位”的意思,也就是4个字节。
对了,差点忘记说RESB 0x1fe-$了。这个美元符号的意思如果不讲,恐怕谁也搞不明白,它
是一个变量,可以告诉我们这一行现在的字节数(如果严格来说,有时候它还会有别的意思,关
于这一点我们明天再讲)。在这个程序里,我们已经在前面输出了132字节,所以这里的$就是132。
因此nask先用0x1fe减去132,得出378这一结果,然后连续输出378个字节的0x00。
那这里我们为什么不直接写378,而非要用$呢?这是因为如果将显示信息从“hello, world”
变成“this is a pen.”的话,中间要输出0x00的字节数也会随之变化。换句话说,我们必须保证软
盘的第510字节(即第0x1fe字节)开始的地方是55 AA。如果在程序里使用美元符号($)的话,
汇编语言会自动计算需要输出多少个00,我们也就可以很轻松地改写输出信息了。
■■■■■
既然可以毫不费力地改写显示的信息,就一定要好好发挥这一功能,让我们的操作系统显示
出自己喜欢的一句话,让它成为一个只属于我们自己的、世界上独一无二的操作系统。不过遗憾
的是现在它还不能显示汉字。当然大家也可以尝试一下,但由于这个程序还没有显示汉字的功能,
所以显示出来的都是乱码,因此大家先将就一下,用英语或拼音吧。
■■■■■
最后再给大家解释一下程序中出现的几个专门术语。时间不早了,我们今天就到这吧。其他
的留待明天再说。
TAB=4….......有的文本编辑器可以调整TAB键的宽度。请使用这种编辑器的人将TAB键的宽度设
定成4,这样源程序更容易读。可能有人说,我这里只能用记事本(notepad),TAB
键宽度固定为8,想调都没法调。没关系,明天笔者来推荐一个好用的文本编辑器。
FAT12格式...(FAT12 Format)用Windows或MS-DOS格式化出来的软盘就是这种格式。我们的
helloos也采用了这种格式,其中容纳了我们开发的操作系统。这个格式兼容性好,
在Windows上也能用,而且剩余的磁盘空间还可以用来保存自己喜欢的文件。
启动区..........(boot sector)软盘第一个的扇区称为启动区。那么什么是扇区呢?计算机读写软
盘的时候,并不是一个字节一个字节地读写的,而是以512字节为一个单位进行读
写。因此,软盘的512字节就称为一个扇区。一张软盘的空间共有1440KB,也就是
1474560字节,除以512得2880,这也就是说一张软盘共有2880个扇区。那为什么
第一个扇区称为启动区呢?那是因为计算机首先从最初一个扇区开始读软盘,然
后去检查这个扇区最后2个字节的内容。

如果这最后2个字节不是55 AA,计算机会认为这张盘上没有所需的启动程序,就会
报一个不能启动的错误。(也许有人会问为什么一定是55 AA呢?那是当初的设计
者随便定的,笔者也没法解释)。如果计算机确认了第一个扇区的最后两个字节正
好是55 AA,那它就认为这个扇区的开头是启动程序,并开始执行这个程序。
IPL.........…....initial program loader的缩写。启动程序加载器。启动区只有区区512字节,实际的
操作系统不像hello-os这么小,根本装不进去。所以几乎所有的操作系统,都是把
加载操作系统本身的程序放在启动区里的。有鉴于此,有时也将启动区称为IPL。
但hello-os没有加载程序的功能,所以HELLOIPL这个名字不太顺理成章。如果有
人正义感特别强,觉得“这是撒谎造假,万万不能容忍!”,那也可以改成其他的
名字。但是必须起一个8字节的名字,如果名字长度不到8字节的话,需要在最后
补上空格。
启动..........….(boot)boot这个词本是长靴(boots)的单数形式。它与计算机的启动有什么关系
呢?一般应该将启动称为start的。实际上,boot这个词是bootstrap的缩写,原指靴
子上附带的便于拿取的靴带。但自从有了《吹牛大王历险记》(德国)这个故事
以后,bootstrap这个词就有了“自力更生完成任务”这种意思(大家如果对详情感
兴趣,可以在Google上查找,也可以在帮助和支持网页http://hrb.osask.jp上提问)。
而且,磁盘上明明装有操作系统,还要说读入操作系统的程序(即IPL)也放在磁
盘里,这就像打开宝物箱的钥匙就在宝物箱里一样,是一种矛盾的说法。这种矛
盾的操作系统自动启动机制,被称为bootstrap方式。boot这个说法就来源于此。如
果是笔者来命名的话,肯定不会用bootstrap 这么奇怪的名字,笔者大概会叫它“多

级火箭式”吧。


作者川合秀实(Hidemi Kawai)译者: 周自恒 /李黎明 / 曾祥江 / 张文旭


1. 计算机只知道01代码,计算机启动时从引导扇区开始执行,文件如下hellos.asm

  1.          
  2.        DB   0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4f  
  3. DB  0x49, 0x50, 0x4c, 0x00, 0x02, 0x01, 0x01, 0x00  
  4. DB  0x02, 0xe0, 0x00, 0x40, 0x0b, 0xf0, 0x09, 0x00  
  5. DB  0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00  
  6. DB  0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x29, 0xff  
  7. DB  0xff, 0xff, 0xff, 0x48, 0x45, 0x4c, 0x4c, 0x4f  
  8. DB  0x2d, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x46, 0x41  
  9. DB  0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00  
  10. RESB    16  
  11. DB  0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c  
  12. DB  0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a  
  13. DB  0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09  
  14. DB  0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb  
  15. DB  0xee, 0xf4, 0xeb, 0xfd, 0x0a, 0x0a, 0x68, 0x65  
  16. DB  0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72  
  17. DB  0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00  
  18. RESB    368  
  19. DB  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa  
  20. DB  0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00  
  21. RESB    4600  
  22. DB  0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00  
  23. RESB    1469432  


2. 使用nasm编译,直接生成软盘映像

  1. nasm -o helloos.img helloos.asm  


 

3.使用bochs可虚拟运行,helloos.bxrc

  1. romimage: file=$BXSHARE\BIOS-bochs-latest, address=0xf0000  
  2. megs: 16  
  3. vgaromimage: $BXSHARE\VGABIOS-lgpl-latest  
  4. floppya: 1_44=helloos.img, status=inserted  
  5. boot: a  
  6. log: bochsout.txt  
  7. parport1: enable=0  
  8. vga_update_interval: 300000  
  9. keyboard_serial_delay: 200  
  10. keyboard_paste_delay: 100000  
  11. floppy_command_delay: 50000  
  12. ips: 4000000  
  13. mouse: enabled=0  
  14. private_colormap: enabled=0  
  15. fullscreen: enabled=0  
  16. screenmode: name="sample"  
  17. i440fxsupport: enabled=0  


4. helloos1.asm=helloos.asm

  1. ;FAT12格式文件系统头部分  
  2.         DB      0xeb, 0x4e, 0x90  
  3.         DB      "HELLOIPL"        
  4.         DW      512       
  5.         DB      1         
  6.         DW      1         
  7.         DB      2         
  8.         DW      224   
  9.         DW      2880      
  10.         DB      0xf0      
  11.         DW      9     
  12.         DW      18    
  13.         DW      2     
  14.         DD      0     
  15.         DD      2880      
  16.         DB      0,0,0x29  
  17.         DD      0xffffffff  
  18.         DB      "HELLO-OS   "     
  19.         DB      "FAT12   "    
  20.         RESB    18            
  21. ;程序主体  
  22.         DB      0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c  
  23.         DB      0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a  
  24.         DB      0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09  
  25.         DB      0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb  
  26.         DB      0xee, 0xf4, 0xeb, 0xfd  
  27. ;显示信息部分  
  28.   
  29.         DB      0x0a, 0x0a    
  30.         DB      "hello, world"  
  31.         DB      0x0a          
  32.         DB      0  
  33.         ;原书中使用下面指令,但这个在nasm中不通过,故使用times  
  34.         ;RESB   0x1fe - $             
  35.         ;times 0x1fe - ($ - $$) DB 0  
  36.                 times 510 - ($-$$) DB 0  
  37.   
  38.         DB      0x55, 0xaa  
  39. ;启动区外输出部分  
  40.         DB      0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00  
  41.         RESB    4600  
  42.         DB      0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00  
  43.         RESB    1469432  


 

5. helloos2.asm=helloos1.asm

  1.         ORG     0x7c00            
  2.   
  3.         JMP     entry  
  4.         DB      0x90  
  5.         DB      "HELLOIPL"        
  6.         DW      512               
  7.         DB      1                 
  8.         DW      1             
  9.         DB      2             
  10.         DW      224               
  11.         DW      2880          
  12.         DB      0xf0          
  13.         DW      9             
  14.         DW      18            
  15.         DW      2             
  16.         DD      0             
  17.         DD      2880          
  18.         DB      0,0,0x29      
  19.         DD      0xffffffff        
  20.         DB      "HELLO-OS   "     
  21.         DB      "FAT12   "    
  22.         RESB    18            
  23.   
  24.   
  25. entry:  
  26.         MOV     AX,0              
  27.         MOV     SS,AX  
  28.         MOV     SP,0x7c00  
  29.         MOV     DS,AX  
  30.         MOV     ES,AX  
  31.   
  32.         MOV     SI,msg  
  33. putloop:  
  34.         MOV     AL,[SI]  
  35.         ADD     SI,1              
  36.         CMP     AL,0  
  37.         JE      fin  
  38.         MOV     AH,0x0e           
  39.         MOV     BX,15             
  40.         INT     0x10              
  41.         JMP     putloop  
  42. fin:  
  43.         HLT                       
  44.         JMP     fin               
  45.   
  46. msg:  
  47.         DB      0x0a, 0x0a        
  48.         DB      "hello, world"  
  49.         DB      0x0a              
  50.         DB      0  
  51.   
  52.         ;RESB   0x7dfe-$          
  53.         ;times   0x7dfe - ( $ - $$ ) DB 0  
  54.                 times 510-($-$$) DB 0  
  55.   
  56.         DB      0x55, 0xaa  
  57.   
  58.         DB      0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00  
  59.         RESB    4600  
  60.         DB      0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00  
  61.         RESB    1469432  

6. FAT12信息

FAT12是MS公司Dos所支持的文件系统之一,当软盘被标准格式化后:每个磁头80个磁道,每个磁道18个扇区,每个扇区512字节,所以标准软盘的容量为:2*80*18*512=1474560B=1440K=1.44M。文件系统数据结构为:

引导程序数据结构


原文地址:https://www.cnblogs.com/xieyuan/p/3787437.html