找回密码
 立即注册
搜索
热搜: 活动 通知
查看: 44|回复: 0

第16章习题

[复制链接]

620

主题

336

回帖

1057

积分

管理员

积分
1057
发表于 2026-3-17 14:07:23 | 显示全部楼层 |阅读模式
第16章习题

1.修改代码清单16-1和15-3,使用户程序能够正常返回到内核,并在显示消息后停机。
答案:将jmp far [fs:TerminateProgram]改为call far [fs:TerminateProgram]。

2.修改代码清单16-1和15-3,使得通过调用门请求读取硬盘扇区的服务时,通过栈传递参数。而且,传递的参数分别是逻辑扇区号、数据段选择子和段内偏移。要求使用arpl指令。
参考答案:
内核程序较为复杂,尽量不改变原有的设计和元素,仅添加新的功能较好。为此,我们需要在内核公用例程段内新增加一个例程read_hard_disk_with_gate并用它创建一个新的调用门。以下是这个新例程的代码。
  1. ;此例程用于说明如何通过请求特权级RPL解决因请求者身份与CPL不同而带来的安全问题
  2. read_hard_disk_with_gate:                   ;从硬盘读取一个逻辑扇区
  3.                                             ;输入:PUSH 逻辑扇区号
  4.                                             ;      PUSH 目标缓冲区在段内的偏移量
  5.                                             ;      PUSH 目标缓冲区所在段的选择子
  6.                                             ;返回:无
  7.          push ebp
  8.          mov ebp,esp

  9.          push eax
  10.          push ebx
  11.          push ds

  12.          mov ax,[ebp+0x08]                  ;获取调用者的CS
  13.          arpl [ebp+0x0c],ax                 ;将数据段选择子调整到真实的请求特权级别
  14.          mov ds,[ebp+0x0c]                  ;用真实的段选择子加载段寄存器DS

  15.          mov eax,[ebp+0x14]                 ;从栈中取得逻辑扇区号
  16.          mov ebx,[ebp+0x10]                 ;从栈中取得缓冲区在段内的偏移量

  17.          ;此部分的功能是读硬盘,并传送到缓冲区。调用现成的例程。
  18.          call sys_routine_seg_sel:read_hard_disk_0

  19.          pop ds
  20.          pop ebx
  21.          pop eax

  22.          pop ebp

  23.          retf 12                        ;必须是参数的总字节数
复制代码

接下来,转到内核数据段,在原来的符号地址检索表末尾添加一个新的条目:
  1.          salt_5         db  '@ReadDiskDataWithGate'
  2.                      times 256-($-salt_5) db 0
  3.                           dd  read_hard_disk_with_gate
  4.                           dw  sys_routine_seg_sel
复制代码

注意修改salt_item_len,将其改为
  1. salt_item_len   equ $-salt_5
复制代码

再转到内核的入口点,找到安装调用门的循环代码。这段代码不能处理调用门中的参数数量部分,所以要将其删除,手动逐个安装调用门。实施:删除原来的循环,插入以下代码:
  1.          ;以下开始安装为整个系统服务的调用门。特权级之间的控制转移必须使用门
  2.          ;安装'PrintString'
  3.          mov eax,[salt_1+256]               ;该条目入口点的32位偏移地址
  4.          mov bx,[salt_1+260]                ;该条目入口点的段选择子
  5.          mov cx,1_11_0_1100_000_00000B      ;特权级3的调用门(3以上的特权级才
  6.                                             ;允许访问),0个参数(因为用寄存器
  7.                                             ;传递参数,而没有用栈)
  8.          call sys_routine_seg_sel:make_gate_descriptor
  9.          call sys_routine_seg_sel:set_up_gdt_descriptor
  10.          mov [salt_1+260],cx                ;将返回的门描述符选择子回填

  11.          ;安装'ReadDiskData'
  12.          mov eax,[salt_2+256]               ;该条目入口点的32位偏移地址
  13.          mov bx,[salt_2+260]                ;该条目入口点的段选择子
  14.          mov cx,1_11_0_1100_000_00000B      ;特权级3的调用门(3以上的特权级才
  15.                                             ;允许访问),0个参数)
  16.          call sys_routine_seg_sel:make_gate_descriptor
  17.          call sys_routine_seg_sel:set_up_gdt_descriptor
  18.          mov [salt_2+260],cx                ;将返回的门描述符选择子回填

  19.          ;安装'PrintDwordAsHexString'
  20.          mov eax,[salt_3+256]               ;该条目入口点的32位偏移地址
  21.          mov bx,[salt_3+260]                ;该条目入口点的段选择子
  22.          mov cx,1_11_0_1100_000_00000B      ;特权级3的调用门(3以上的特权级才
  23.                                             ;允许访问),0个参数(因为用寄存器
  24.                                             ;传递参数,而没有用栈)
  25.          call sys_routine_seg_sel:make_gate_descriptor
  26.          call sys_routine_seg_sel:set_up_gdt_descriptor
  27.          mov [salt_3+260],cx                ;将返回的门描述符选择子回填

  28.          ;安装'TerminateProgram'
  29.          mov eax,[salt_4+256]               ;该条目入口点的32位偏移地址
  30.          mov bx,[salt_4+260]                ;该条目入口点的段选择子
  31.          mov cx,1_11_0_1100_000_00000B      ;特权级3的调用门(3以上的特权级才
  32.                                             ;允许访问),0个参数(因为用寄存器
  33.                                             ;传递参数,而没有用栈)
  34.          call sys_routine_seg_sel:make_gate_descriptor
  35.          call sys_routine_seg_sel:set_up_gdt_descriptor
  36.          mov [salt_4+260],cx                ;将返回的门描述符选择子回填

  37.          ;安装'ReadDiskDataWithGate'
  38.          mov eax,[salt_5+256]                  ;该条目入口点的32位偏移地址
  39.          mov bx,[salt_5+260]                   ;该条目入口点的段选择子
  40.          mov cx,1_11_0_1100_000_00011B      ;特权级3的调用门(3以上的特权级才
  41.                                             ;允许访问),3个参数。
  42.          call sys_routine_seg_sel:make_gate_descriptor
  43.          call sys_routine_seg_sel:set_up_gdt_descriptor
  44.          mov [salt_5+260],cx                   ;将返回的门描述符选择子回填
复制代码

接下来修改用户程序c15_app.asm。
由于是使用内核中新添加的调用门,所以要在头部段中,将
  1.          ReadDiskData     db  '@ReadDiskData'
  2.                      times 256-($-ReadDiskData) db 0
复制代码

修改为
  1.          ReadDiskData     db  '@ReadDiskDataWithGate'
  2.                      times 256-($-ReadDiskData) db 0
复制代码


既然是通过栈传递参数,那就删除第74~77行,插入以下指令:
  1.         push dword 100                ;压入起始逻辑扇区号
  2.         push dword buffer        ;压入段内偏移量
  3.         push ds                        ;压入数据段选择子
  4.         call far [fs:ReadDiskData]          ;段间调用
复制代码

为保证程序正常工作,将代码段最后的
  1. jmp far [fs:TerminateProgram]
复制代码
改成
  1. call far [fs:TerminateProgram]
复制代码

由于文件较大,这里将它作为附件发布。




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|鼠侠网 ( 吉ICP备19001332号 )

GMT+8, 2026-3-30 16:15 , Processed in 0.263412 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表