jmp 1002:0015
它实际上就是跳转到下面一行:
mov ax, 1000 //指令地址:0x10035
…
接下来可以看到代码一直运行到boothead.s中调用boot函数的汇编代码:
…
jmp no_ext
adj_ext:
add 14(di), bx ! Add ext mem above 16M to mem below 16M
no_ext:
! Time to switch to a higher level language (not much higher)
call _boot //调用boot函数
结合/boot文件的反汇编代码,可以判定boot函数的地址为0x1267a。
启动Bochs,然后在调试窗口设置断点后运行:
<bochs:1>pb 0x10124 //设置物理地址断点
<bochs:2>c
运行一段时间后,Bochs停在了0x10124处。接下来单步运行进入boot函数:
<bochs:3>s
<bochs:4>u /10 //列出反汇编代码
0001267a :( ): push bp
0001267b :( ): mov bp, sp
0001267d :( ): call .+0xe6cb
00012680 :( ): call .+0xeccc
…
从列出的反汇编代码可以看出execute函数的调用应该在0x1002:266a这一行,所以设置断点:
<bochs:5>pb 0x1268a
不过遗憾的是系统并没有在预料的地方停下来,而是一直运行下去了,看来一定是因为某种原因使断点失效了。经过测试发现,汇编语句在第一个call语句(initialize函数)就没有返回,这是什么原因呢?其实只要看一看initialize函数的代码就可以发现,这个函数把启动程序拷贝到了low memory(640k)的远端(far end),也就是接近640k的地方。所以整个启动代码的基地址在这个函数中的某一句之后就全部改变了,看来要想完全跟踪启动代码还要费一番功夫。
<bochs:6>pb 0x1267d //在initialize函数处设置断点
<bochs:7>s //进入函数
<bochs:8>u /20
使拷贝到新地址的启动程序运行的是initialize函数中调用的第二个过程relocate,它位于boothead.s中。所以可以先找到后面的第二个call指令(即relocate函数)进入,这个汇编函数最后返回的地址就是新定位的地址了。
<bochs:8>pb 0x10e13 //在relocate的入口设置断点(下一条指令的地址是0x10e16)
<bochs:9>c
<bochs:10>s //进入relocate
<bochs:11>u /20
<bochs:12>pb 0x10251 //在relocate返回点设置断点
<bochs:13>c
<bochs:14>s
可以看间,返回的新地址是0x93606,boot的代码在机器上被重新定位到了0x93606-0x10e16=0x827f0处。
现在我们可以重新设置execute函数的断点。它应该位于0x94e7a,所以输入以下内容:
<bochs:14>pb 0x94e7a
再运行可以发现,Bochs果然停在了预料的位置,看来前面的分析过程没有问题。接下来就可以进一步跟踪Minix的启动过程了。