第三章主要讲了启动区和从启动区载入操作系统程序。
书中一个装载磁盘数据的代码示例:
MOV AX, 0x0820
MOV ES, AX
MOV CH, 0
MOV DH, 0
MOV CL, 2
MOV AH, 0x02
MOV AL, 1
MOV BX, 0
MOV DL, 0x00
INT 0x13
0x13就是触发读写磁盘操作的中断序号,它需要的参数如下(部分):
- AH: 0x02(读盘),0x03(写盘)
- AL: 同时处理的扇区数(连续的扇区)
- CH: 柱面号(一组同心圆环中的一个)
- CL: 扇区号(圆环上的一个扇形区域)
- DH: 磁头号(0或1,表示磁盘的正面或反面)
- DL: 驱动器号
- ES:BX: 缓冲地址(读磁盘时,表示读出数据放到内存的哪一块)
书中说内存的0x8000-0x81ff这512个字节是留给启动区的,又说0x7c00-0x7dff用于启动区。这两者的区别是,启动区一开始就默认装载到0x8000这一段。而0x7c00是在之前的程序中用ORG 0x7c00确定的,这是程序运行时所占用的内存空间。
书中所说的
(1)文件名会写在0x002600以后的地方;
(2)文件的内容会写在0x004200以后的地方。
是指磁盘上的地址。装载到内存中后,需要加上刚才的0x8000才是实际的地址。
启动区的作用是把真正的操作系统程序装载到内存中,然后跳转到操作系统的程序。如书中所示,在启动区程序的末尾使用JMP指令跳转到刚才计算好的操作系统程序开始的位置。
对ORG指令的理解
网上大多数都是说,ORG指令是指它之后的程序的地址从它指定的地址开始。但是看书59页的haribote.nas,这段程序不是已经被启动区的程序加载到0xc200了吗,为什么还要用ORG指令再指定它的位置?要是两个指定的不同,那该听谁的?
到后来发现根本不是这样。ORG指令其实是一条伪指令,只有编译器会看到它,而它不会变成可执行的机器码。它的使命在编译的时候就结束了。
使用二进制编辑器打开编译出来的机器码,可以看到,指令根本没有地址,都是一条一条排下来的。那么ORG怎么决定它之后的程序从哪开始呢?
其实,真正决定程序地址在哪的并不是ORG。比如59页的haribote.nas,它已经被启动区程序加载到0xc200了。ORG的作用,是把代码中引用到了标签的地方把标签替换为实际的地址。例如:
ORG 0xc200
msg DB "hello world"
MOV SI, msg
在这里面,ORG指定的地址不同,则msg的地址就不同,MOV指令的机器码也就不同。这些都是在编译阶段根据ORG指定的地址所确定的。而在59页的代码中,之所以ORG敢这么写,是因为我们知道这段代码已经被启动区程序放到0xc200这个位置了。
另外一个例子:
VAR1 DB 0x01
ORG 0x100
VAR2 DB 0x02
MOV AX, VAR1
MOV AX, VAR2
像这样,编译之后,第一条MOV指令的VAR1就变成了0x0000,第二条的VAR2变成了0x0100。
目前只是在这本书的nask编译器下试过,别的编译器不知道会有什么不同。