任务和特权级保护(四)——《x86汇编语言:从实模式到保护模式》读书笔记35

任务和特权级保护(四)——《x86汇编语言:从实模式到保护模式》读书笔记35

7. 正式进入用户程序的局部空间

67           mov ebx,message_1
68           call far [fs:PrintString]
69  
70           mov eax,100                         ;逻辑扇区号100
71           mov ebx,buffer                      ;缓冲区偏移地址
72           call far [fs:ReadDiskData]          
73  
74           mov ebx,message_2
75           call far [fs:PrintString]
76  
77           mov ebx,buffer
78           call far [fs:PrintString]           
79  
80           jmp far [fs:TerminateProgram]       ;将控制权返回到系统

第67~78,都是通过调用门使用了内核提供的例程。

第80行,需要特别说明。
[fs:TerminateProgram] 处确实是一个调用门,但是这里是通过jmp far来引用,会发生什么情况呢?

8. 代码的编译和调试

8.1. Makefile文件

BIN = c13_mbr.bin c14_core.bin c13.bin empty
A_DIR = /home/cjy/a.img
C_DIR = /home/cjy/c.img

all:$(BIN)

.PHONY:all clean

c13_mbr.bin:c13_mbr.asm
    nasm $< -o $@
    dd if=$@ of=$(A_DIR)

c14_core.bin:c14_core.asm
    nasm $< -o $@ 
    dd if=$@ of=$(C_DIR) bs=512 seek=1 conv=notrunc

c13.bin:c13.asm
    nasm $< -o $@
    dd if=$@ of=$(C_DIR) bs=512 seek=50 conv=notrunc

empty:diskdata.txt
    dd if=$< of=$(C_DIR) bs=512 seek=100 conv=notrunc
    touch $@

clean:
    $(RM) $(BIN)

8.2. 编译

make之后,我们发现报错了:

c14_core.asm:645: error: operation size not specified
c14_core.asm:662: error: operation size not specified

不用担心,只要在这两行加上 dword修饰符即可。

8.3. 运行结果与分析

看上图,我们发现用户程序没有成功返回到内核,也就是下面这段代码根本没有执行。

866  return_point:                             ;用户程序返回点
867         mov eax,core_data_seg_sel          ;因为c14.asm是以JMP的方式使用调 
868         mov ds,eax                         ;用门@TerminateProgram,回到这 
869                                            ;里时,特权级为3,会导致异常。 
870         mov ebx,message_6
871         call sys_routine_seg_sel:put_string
872
873         hlt

再看看Bochs的调试界面,发现重启了!

导致重启的是黄色划线的那句指令。查看日志,发现产生了一般保护异常。也就是说

80           jmp far [fs:TerminateProgram]       ;将控制权返回到系统

这句代码会产生一般保护异常。

究其原因,不难理解。

因为目标代码段是非一致的,所以用jmp far指令转移的时候,CPL必须等于目标代码段的DPL。但是我们的实验不满足这个条件,因为CPL=3,目标代码段的DPL=0.所以,自然就产生异常了。

怎么解决呢?本章的习题1刚好问了这个问题。

修改代码清单14-1和13-3,使用户程序能够正常返回到内核,并在显示消息后停机。

单单就题目要求,有一种比较省事的解决方法,只需要修改代码清单13-3中的第80行,把jmp far改成call far就行了。
因为CPL=3;RPL=3;调用门描述符的DPL=3;目标代码段的DPL=0;完全符合call far的条件。

修改后再次编译、运行,结果如下图:

可以看到,确实返回到了全局空间。而且Bochs调试界面也没有重启。

这篇博文的内容就到这里。下次我们说一下习题2,敬请关注…

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值