自制操作系统06-7c00在程序中的作用

今天先做的是.c文件的分割,这个学过c语言的同学都知道,就是把声明抽取到.h文件,分割的.c文件都引用一下这个文件就可以了。
但有一点我重复下include双引号("")表示是从源文件所在文件夹,include尖括号(<>)是从编译器的文件夹下找.h文件。
本来我想顺着作者的思路继续学下去,可是讲什么段地址寄存器,中断。我可是一个实验都没做,不理解,继续看下去也没什么意思。
我再回头看,很地方不明白.
1.最开始是DB与RESB命令生成软盘,可以理解,反正与直接写二进制一样的,不需理解二进制的含义。
2.开始解释字节的含义,这里有开始有问题了。

首先,ORG是个伪指令,我们把有无ORG两种情况,生成的文件分别用bz打开看16进制:


第一个前三个字节是DB生成的"0xeb, 0x4e, 0x90"可以理解,但第二个是
ORG        0x7c00
JMP        entry
DB        0x90
这三句汇编才生成三个字节?然后我才学习到nasm a.asm -l a.lst可以生成字节码与汇编的对应关系,其实是这样的对应的。
    
1                                  ; hello-os
2                                  ; TAB=4
3                                  
4                                  ORG	0x7c00; 把程序以下程序加载到内存的0x7c00,即引导区
5                                  
6                                  ; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
7                                  
8 00000000 EB4E                    		JMP		entry
9 00000002 90                      		DB		0x90


就是说ORG这句没用,没有生成字节。那我去掉试试。做这个试验时发现一个问题,以前生成的软盘映像文件大小不会影响Vmware运行。但在VMVirtualBox却必须要1440kb,多1kb都不行。
去掉ORG,试验失败,显示了一个$,没有"hello world"。这是为什么?
对比了一下映像文件,原来在0x5e的地方,两个文件不一样了。而且有ORG的地方就是写的7c。为什么是0x5e(94)我没查到,但0-512都是FAT12的引导扇区,是有固定解析规则的,
这个规则在0-62个字节都有明确的说明。我对照lst文件看一下,有ORG的是这样的:
32 00000050 B80000                          MOV        AX,0            ; 初始化寄存器
33 00000053 8ED0                            MOV        SS,AX            ;
34 00000055 BC007C                          MOV        SP,0x7c00
35 00000058 8ED8                            MOV        DS,AX
36 0000005A 8EC0                            MOV        ES,AX
37                                  
38 0000005C BE[7400]                        MOV        SI,msg
39                                  putloop:
40 0000005F 8A04                            MOV        AL,[SI]
41 00000061 83C601                          ADD        SI,1            ; SIに1を足す
42 00000064 3C00                            CMP        AL,0

哇,这5E的地址在MOV SI,msg这句上。为了搞明白这个问题,我们需要使用另一个工具:bochs。打开bochsdbg后,用b 0x7c00,然后执行c,跳到内存的7c00处,其实这就是本程序的开始位置。单步跟踪(n)到mov si,msg处,对比有org和无org的区别,可以看到无org的是这样:


在nasm编译时,nasm计算出msg标号的位置相对于程序开始是0x74的位置。没有org命令,那么就是0x0074了。而有org的是这样的:


mov si,msg中的msg的地址变成了0x7c74了, 这就是nasm在编译时看到有个org 0x7c00,那么msg的地址就应该是0x7c00+0x74=0x7c74了。在内存中0x7c74存放的字节是0a,所以后面那句命令让al的值为0a了。而无org的是0x0074,不知道里面放的是什么值,就会报错。


总之,要写bootloader得从看懂汇编开始。

为什么是7c00而不是其它的什么值,阮一峰的这篇文章有介绍:http://www.ruanyifeng.com/blog/2015/09/0x7c00.html

于是我有了个想法,回头重新把作者的专用工具换成市场上通用的工具,这样即使看不懂,也有很多可以学习的资料,可慢慢看。那就从make工具开始,作者用的是gnu的make。

首先从ftp://ftp.gnu.org/gnu/make下载一个较老的版本,我下载的是3.81。里面有个build_w32.bat的构建文件,但他用了c语言编译器(cl.exe)。我于是先安装了一个vc6.0。如果已经有安装好的gnumake,就不用安装vc6.0,生成好的gnumake下面有个WinRel文件夹,其它系统直接用这个就行了。对了,我这个是winxp里做的,win7应该也没有问题。把cl.exe路径配置进path环境变量就可以构建成功了,构建完会生成一个WinRel文件夹,里面会有我们需要的gnumake.exe等文件。把WinRel的路径配置进环境变量。后面就可以不用作者的make,改用gnumake了,如下图:

后面准备改用masm来替换nask.exe这个工具,这是个大活。

文/中中 浏览次数:0次   2020-04-14 16:03:43

相关阅读


评论: