《自己动手编写操作系统》中的第4章读取扇区的示例程序似乎无法正确运行

red-fly 2015-06-02 07:56:59
《自己动手编写操作系统》中,第四章的程序 chapter4\b\boot.asm似乎无法正常运行。
我把它编译成boot.bin后,没有进行其它操作(即没有把loader文件拷贝到分区上),启动后无法打印:No LOADER
如果我在开始的时候就调用DispStr,就可以打印出来:Booting
不知道有没有谁遇到过这个问题??


如下是比较靠近开始位置的代码,我加入了几和注释掉的代码:

LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
; mov dx, [wRootDirSizeForLoop]
; add dx, 30h
; mov [StringBuf], dx
; call DispStr1
cmp word [wRootDirSizeForLoop], 0

注释掉的几行,是我想把wRootDirSizeForLoop的值打印出来,结果弄不成事,打印不出来。DispStr1是一个新的函数,是根据DispStr和该书第一个程序的打印进行的修改。
正常情况下,wRootDirSizeForLoop的值14应该被连续打印出来才对,至少要在屏幕上显示到最后的0才是正常的。
我估计这个程序是哪个地方需要做个小的修改才行,但对汇编一巧不通,改不好
...全文
396 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
red-fly 2015-06-29
  • 打赏
  • 举报
回复
先记录一个小情况。 今天再次添加一个打印,目的仍然是把wRootDirSizeForLoop的值打印出来,对之前的DispStr1进行了少许修改,主要是添加了对es附值为0的语句,函数的调用如下:

LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
        mov     ax, word [wRootDirSizeForLoop]
        add     ax, 0x30
        mov     [StringBuf], ax
        call DispStr1
由于我没有把wRootDirSizeForLoop的值转换成可显示的字符串,所以这里我对这个数字加上了0x30以便能够显示出来,当然超过9的就暂不管它是否可以正常显示了。 其中的StringBuf定义如下:

StringBuf               db      "tempbuf "
DispStr1的函数如下:

DispStr1:
        push    es
        mov     ax, 0
        mov     es, ax
        mov     dh, [StringBuf]
        sub     dh, 0x30         ; 这一行会改变显示效果
	mov	ax, StringBuf
	mov	bp, ax			; ┓
	mov	cx, 8            	; CX = 串长度
	mov	ax, 01301h		; AH = 13,  AL = 01h
	mov	bx, 0007h		; 页号为0(BH = 0) 黑底白字(BL = 07h)
	mov	dl, 0
	int	10h			; int 10h
	pop     es
	ret
其中注意对dh的操作,如果我不对dh附值,即dh值为0时,最终的打印如下: 打印全部集中在第一行的开始位置。 如果dh被附值,如代码所示(注意减去0x30是因为在调用函数的时候加了0x30),则打印结果如下: 这样就可以清楚 地看到值确实在一次次地减小了。 本次记录有两点: 1. 在显示之前,需要清空es的值,否则显示的内容是空 2. 如果要改变显示输出的行,改变dh的值为对应行号即可
red-fly 2015-06-07
  • 打赏
  • 举报
回复
今天再试,一样,bochs还是可以正常通过,即打印 NO LOADER,昨天和今天,vmware都仍然还是不可以
red-fly 2015-06-06
  • 打赏
  • 举报
回复
我不知道是怎么回事,有两个使我糊涂的情况: 1. 就像上面说的那些情况,时好时坏,我把后面的dx、cx变量也附什给wDigBuf就没有出现过问题。这个问题暂时先不用管它了,反正也能跑出结果了。 2. 如果我直接运行,它就什么也没有打印,如果我仔细地单步运行一整次,关键似乎是要每次在

cmp    word [wRootDirSizeForLoop], 0
这一行断点停住,它就能跑出结果为NO LOADER,然后我再重新启动不用断点也会有这个结果了(有这个结果才是正常的,因为我没有把loader写入进来),晕死了,这个在两台电脑上都是一样的情况,我真糊涂了
wang0635 2015-06-05
  • 打赏
  • 举报
回复
引用 7 楼 jszj 的回复:
call DispStr1 这一行是我添加的,它没有内容打印出来,可能还是我写的不对,这一行暂不追究。 今天下午上网上搜索了一下: http://www.cnblogs.com/hongzg1982/articles/2116643.html 说明了如何调试这种程序,采用bochs,终于可以单步运行了。 我用的是2.6.8版本的。 现在基本上发现似乎是dx、cx的计数总是不对,循环了多遍,这两个寄存器的值硬是没有减小!对应的打印如下: (0) [0x000000007c84] 0000:7c84 (unk, ctxt): dec dx ;4a 我想后面的那个4a应该就是dx的值,如果是,那我发现每次循环到这里,这个值一直不变!所以这个搜索的循环就没办法退出来,晕死了。有用过的大侠出来指点一二 我打印寄存器的值,似乎看不到dx、cx 另外一个命令:
rcx rdx后面 就是cx dx的值吧
red-fly 2015-06-05
  • 打赏
  • 举报
回复
似乎看不到,如下所示: 这一语句已经把0x31送入到了AL中,但在显示的寄存器中却看不到有哪个是0x31的值
wang0635 2015-06-05
  • 打赏
  • 举报
回复
引用 14 楼 jszj 的回复:
有点糊涂了,我再把wDigBuf的会子值改为

mov     word [wDigBuf], SectorNoOfRootDirectory
也能成功了,这不是在耍我吗?Bochs!
你比原来多执行了一条指令嘛,看来我的猜测是对的:显示的是准备但还没有执行的指令
red-fly 2015-06-05
  • 打赏
  • 举报
回复
引用 12 楼 wang0635 的回复:
注意,显示的指令是刚刚执行过的那一条呢,还是下一条?如果是后者,就没有问题了
这个还真没有注意呢
red-fly 2015-06-05
  • 打赏
  • 举报
回复
有点糊涂了,我再把wDigBuf的会子值改为

mov     word [wDigBuf], SectorNoOfRootDirectory
也能成功了,这不是在耍我吗?Bochs!
red-fly 2015-06-05
  • 打赏
  • 举报
回复
再试了一次,把附值方式修改成个数字:

mov word [wSectorNo], SectorNoOfRootDirectory
mov word [wDigBuf], 17
结果就附值成功了: 和上面的对比的结果,结论是为什么一个变量不能同时给另外两个变量附值?
wang0635 2015-06-05
  • 打赏
  • 举报
回复
注意,显示的指令是刚刚执行过的那一条呢,还是下一条?如果是后者,就没有问题了
red-fly 2015-06-05
  • 打赏
  • 举报
回复
刚刚只把两个附值的语句调换了一下顺序,即:

mov     word [wDigBuf], SectorNoOfRootDirectory
mov	word [wSectorNo], SectorNoOfRootDirectory
结果wSectorNo附值失败了: 原来是第二个附值失败,和变量没啥关系。 那这又是咋回事呢?奇怪了
red-fly 2015-06-05
  • 打赏
  • 举报
回复
为了把值打印出来,新定义了一个变量wDigBuf,其形式和wSectorNo完成一样: 然后在开始的位置同wSectorNo一样附值: 结果wSectorNo附值成功,而新变量wDigBuf不成功: 这是什么情况?好奇怪
一根烂笔头 2015-06-04
  • 打赏
  • 举报
回复
好像是可以的,有人做过,你再仔细研究研究!
red-fly 2015-06-04
  • 打赏
  • 举报
回复
引用 3 楼 zhao4zhong1 的回复:
楼主要不学学怎么使用WinDbg或Turbo Debug远程连接调试实体DOS或虚拟DOS机的启动过程? 仅是建议,因为我也没实际做过。
暂时对这个兴趣不太大,呵呵 如果要弄,估计还得有很多工具什么需要准备的,相当麻烦 我准备依照前面一个章节中打印内存内容的办法来试试
red-fly 2015-06-04
  • 打赏
  • 举报
回复
call DispStr1 这一行是我添加的,它没有内容打印出来,可能还是我写的不对,这一行暂不追究。 今天下午上网上搜索了一下: http://www.cnblogs.com/hongzg1982/articles/2116643.html 说明了如何调试这种程序,采用bochs,终于可以单步运行了。 我用的是2.6.8版本的。 现在基本上发现似乎是dx、cx的计数总是不对,循环了多遍,这两个寄存器的值硬是没有减小!对应的打印如下: (0) [0x000000007c84] 0000:7c84 (unk, ctxt): dec dx ;4a 我想后面的那个4a应该就是dx的值,如果是,那我发现每次循环到这里,这个值一直不变!所以这个搜索的循环就没办法退出来,晕死了。有用过的大侠出来指点一二 我打印寄存器的值,似乎看不到dx、cx 另外一个命令:
此后三年 2015-06-04
  • 打赏
  • 举报
回复
写汇编代码啊? call DispStr1 正常返回了吗。
赵4老师 2015-06-03
  • 打赏
  • 举报
回复
楼主要不学学怎么使用WinDbg或Turbo Debug远程连接调试实体DOS或虚拟DOS机的启动过程? 仅是建议,因为我也没实际做过。
red-fly 2015-06-03
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
下载了Turb Debugger,但似乎用不好。情况如下 需要在dos运行它(tb),这不是关键,关键是编译出来的程序需要在dos下运行而不能在windows下运行。这个编译本身没有问题,很容易,但编译出来.com文件后要把它放到虚拟机的dos中,这个vpc无法访问我的主机windows,所以没有办法运行.com文件,而只能编译成.bin写入磁盘映像文件中,然后由vpc加载此映像文件并运行其中的程序。这种情况下,这个tb似乎就没法用了。 所以,我才想加个打印把变量的值打印出来看看
赵4老师 2015-06-03
  • 打赏
  • 举报
回复
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程! 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧