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

第14章习题

[复制链接]

620

主题

336

回帖

1057

积分

管理员

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

1.修改本章代码清单,使之可以检测1MB以上的内存空间(从地址0x00100000开始,不考虑高速缓存的影响)。要求:对内存的读写按双字的长度进行,并在检测的同时显示已检测的内存数量。建议对每个双字单元用两个花码0x55AA55AA和0xAA55AA55进行检测。
答案:
此题通过保护模式下的内存访问练习,综合考察巩固前面已经学过的知识,包括GDT,描述符,等等。
以下程序用了1个小时编写,并且已验证。2026-03-16,周一
  1. ;检测物理内存并显示进度
  2. ;最终定格的数字就是你的内存的总字节数。
  3. ;这是一个主引导扇区程序,要写入主引导扇区再运行!!

  4.          ;设置堆栈段和栈指针
  5.          mov eax,cs
  6.          mov ss,eax
  7.          mov sp,0x7c00

  8.          ;计算GDT所在的逻辑段地址
  9.          mov eax,[cs:pgdt+0x7c00+0x02]      ;GDT的32位物理地址
  10.          xor edx,edx
  11.          mov ebx,16
  12.          div ebx                            ;分解成16位逻辑地址

  13.          mov ds,eax                         ;令DS指向该段以进行操作
  14.          mov ebx,edx                        ;段内起始偏移地址

  15.          ;创建0#描述符,它是空描述符,这是处理器的要求
  16.          mov dword [ebx+0x00],0x00000000
  17.          mov dword [ebx+0x04],0x00000000

  18.          ;创建1#描述符,这是一个数据段,对应0~4GB的线性地址空间
  19.          mov dword [ebx+0x08],0x0000ffff    ;基地址为0,段界限为0xfffff
  20.          mov dword [ebx+0x0c],0x00cf9200    ;粒度为4KB,存储器段描述符

  21.          ;创建保护模式下初始代码段描述符
  22.          mov dword [ebx+0x10],0x7c0001ff    ;基地址为0x00007c00,512字节
  23.          mov dword [ebx+0x14],0x00409800    ;粒度为1个字节,代码段描述符

  24.          ;创建以上代码段的别名描述符
  25.          mov dword [ebx+0x18],0x7c0001ff    ;基地址为0x00007c00,512字节
  26.          mov dword [ebx+0x1c],0x00409200    ;粒度为1个字节,数据段描述符

  27.          ;保护模式下的栈段描述符
  28.          mov dword [ebx+0x20],0x7c00fffe    ;基地址为0x00007c00,界限为0xffffe
  29.          mov dword [ebx+0x24],0x00cf9600    ;粒度为4KB,向下扩展

  30.          ;初始化描述符表寄存器GDTR
  31.          mov word [cs: pgdt+0x7c00],39      ;描述符表的界限

  32.          lgdt [cs: pgdt+0x7c00]

  33.          in al,0x92                         ;南桥芯片内的端口
  34.          or al,0000_0010B
  35.          out 0x92,al                        ;打开A20

  36.          cli                                ;中断机制尚未工作

  37.          mov eax,cr0
  38.          or eax,1
  39.          mov cr0,eax                        ;设置PE位

  40.          ;以下进入保护模式... ...
  41.          jmp 0x0010:dword flush             ;16位的描述符选择子:32位偏移

  42.          [bits 32]
  43.   flush:
  44.          ;0x08->4GB数据段选择子;0x10->初始代码段选择子;
  45.          ;0x18->代码段别名段选择子;0x20->栈段选择子。

  46.          mov eax,0x0008                     ;加载数据段(0..4GB)选择子
  47.          mov ds,eax
  48.          mov es,eax
  49.          mov fs,eax
  50.          mov gs,eax

  51.          mov eax,0x0020                     ;0000 0000 0010 0000
  52.          mov ss,eax
  53.          xor esp,esp                        ;ESP <- 0

  54.          mov eax,0x100000                   ;初始的物理地址

  55.   do_again:
  56.          call show_addr                     ;显示这个地址

  57.          ;以下测试这个地址。
  58.          mov dword [eax],0x55aa55aa
  59.          cmp dword [eax],0x55aa55aa
  60.          jne do_exit

  61.          mov dword [eax],0xaa55aa55
  62.          cmp dword [eax],0xaa55aa55
  63.          jne do_exit

  64.          add eax,4
  65.          jmp do_again

  66.          ;最终定格的数字就是你的内存的总字节数。

  67.   do_exit:
  68.          jmp $

  69. ;-------------------------------------------------------------------------------
  70. ;显示地址                        输入:EAX=地址的数值
  71. show_addr:
  72.          push eax
  73.          push ebx
  74.          push ecx
  75.          push edx

  76.          ;以下分解和压栈每个数位
  77.          mov ebx,10
  78.          xor cx,cx               ;cx用来保存压栈次数以便将来出栈
  79.      @d:
  80.          inc cx
  81.          xor edx,edx
  82.          div ebx
  83.          or dl,0x30
  84.          push dx
  85.          cmp eax,0
  86.          jne @d

  87.          ;以下显示各个数位
  88.          xor eax,eax
  89.      @a:
  90.          pop dx
  91.          mov dh,0x07
  92.          mov [eax+0xb8000],dx    ;通过4GB段访问显存
  93.          add eax,2
  94.          loop @a

  95.          pop edx
  96.          pop ecx
  97.          pop ebx
  98.          pop eax

  99.          ret
  100. ;-------------------------------------------------------------------------------
  101.   pgdt  dw 0
  102.         dd 0x00007e00

  103.         times 510-($-$$) db 0
  104.                          db 0x55,0xaa
复制代码

2.有一个向下扩展的段,描述符中的B位和G位都是“1”。请问,如果希望段的大小为8KB,那么,描述符中的界限值应当是多少?
答案:
由于B位是1,则段界限的上界是 0xFFFFFFFF。段大小8KB,则下界限是0xFFFFFFFF-0x2000=0xFFFFDFFF
设描述符中的界限值是x,则0xFFFFDFFF=x*0x1000+0xFFF
求得x=0xFFFFD

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

本版积分规则

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

GMT+8, 2026-3-30 18:19 , Processed in 0.237278 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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