鱼C论坛

 找回密码
 立即注册
查看: 3973|回复: 19

保护模式问题(LDT和自定义段基址的段的冲突问题)

[复制链接]
发表于 2013-1-7 21:05:42 | 显示全部楼层 |阅读模式
20鱼币
本帖最后由 张国祥 于 2013-1-7 21:13 编辑
  1. %include "pm.inc"
  2. org 0100h
  3. jmp start

  4. [SECTION .gdt]
  5. GDT_DESC:                Descriptor        0,0,0
  6. NORMAL_DESC:        Descriptor        0,0ffffh,DA_DRW
  7. RETURN_16_DESC:        Descriptor        0,0ffffh,DA_C
  8. MAIN_DESC:                Descriptor        0,mainlen-1,DA_C+DA_32
  9. DISP_DESC:                Descriptor        0b8000h,0ffffh,DA_DRW
  10. STK_DESC:                Descriptor        0,TopOfStk+1,DA_DRW+DA_32
  11. DATA_DESC:                Descriptor        0,datalen-1,DA_DRW
  12. LDT_DESC:                Descriptor        0,ldtlen-1,DA_LDT
  13. TEST_DESC:                Descriptor        500000h,0ffffh,DA_DRW
  14. ;test和ldt两个描述符是不是不能共存

  15. gdtlim                equ        $-$-1
  16. ;注意长度和界限的区别
  17. dd 0

  18. SEL_NORMAL                EQU                NORMAL_DESC-GDT_DESC
  19. SEL_RETURN_16        EQU                RETURN_16_DESC-GDT_DESC
  20. SEL_MAIN                EQU                MAIN_DESC-GDT_DESC
  21. SEL_DISP                EQU                DISP_DESC-GDT_DESC
  22. SEL_STK                        EQU                STK_DESC-GDT_DESC
  23. SEL_DATA                EQU                DATA_DESC-GDT_DESC
  24. SEL_LDT                        EQU                LDT_DESC-GDT_DESC

  25. SEL_TEST                EQU                TEST_DESC-GDT_DESC


  26. [SECTION .ldt]
  27. ldt:
  28. L_CODE_DESC:        Descriptor        0,lcodelen-1,DA_C+DA_32
  29. ldtlen                equ        $-$

  30. SEL_L_CODE                EQU                L_CODE_DESC-ldt+SA_TIL

  31. [SECTION .lcode]
  32. [BITS 32]
  33. lcode:
  34.         mov edi,160*0+2*40
  35.         mov ah,0ah
  36.         mov al,'L'
  37.         mov [gs:edi],ax
  38.         jmp SEL_RETURN_16:0
  39.         
  40. lcodelen                equ        $-$

  41. [SECTION .data1]
  42. data:
  43.         RMSPValue        dw 0
  44.         pmmsg:                db 'Protect Mode!',0
  45.         pmmsgost        equ        pmmsg-$
  46. datalen                        equ        $-$

  47. [SECTION .stk]
  48. stk:
  49.         times 512 db 0
  50. TopOfStk                equ        $-$-2

  51. [SECTION .start]
  52. [BITS 16]
  53. start:
  54.         mov ax,cs
  55.         mov ds,ax
  56.         mov es,ax
  57.         mov ss,ax
  58.         mov sp,0100h
  59.         
  60.         mov [GoToReal+3],ax
  61.         mov [RMSPValue],sp
  62.         
  63.         ;初始化
  64.         movzx eax,ax
  65.         shl eax,4
  66.         add eax,main
  67.         mov word [MAIN_DESC+2],ax
  68.         shr eax,16
  69.         mov byte [MAIN_DESC+4],al
  70.         mov byte [MAIN_DESC+7],ah
  71.         
  72.         mov ax,ds
  73.         movzx eax,ax
  74.         shl eax,4
  75.         add eax,data
  76.         mov word [DATA_DESC+2],ax
  77.         shr eax,16
  78.         mov byte [DATA_DESC+4],al
  79.         mov byte [DATA_DESC+7],ah
  80.         
  81.         mov ax,ds
  82.         movzx eax,ax
  83.         shl eax,4
  84.         add eax,return16
  85.         mov word [RETURN_16_DESC+2],ax
  86.         shr eax,16
  87.         mov byte [RETURN_16_DESC+4],al
  88.         mov byte [RETURN_16_DESC+7],ah
  89.         
  90.         mov ax,ds
  91.         movzx eax,ax
  92.         shl eax,4
  93.         add eax,ldt
  94.         mov word [LDT_DESC+2],ax
  95.         shr eax,16
  96.         mov byte [LDT_DESC+4],al
  97.         mov byte [LDT_DESC+7],ah
  98.         
  99.         mov ax,cs
  100.         movzx eax,ax
  101.         shl eax,4
  102.         add eax,lcode
  103.         mov word [L_CODE_DESC+2],ax
  104.         shr eax,16
  105.         mov byte [L_CODE_DESC+4],al
  106.         mov byte [L_CODE_DESC+7],ah
  107.         
  108.         mov ax,ss
  109.         movzx eax,ax
  110.         shl eax,4
  111.         add eax,stk
  112.         mov word [STK_DESC+2],ax
  113.         shr eax,16
  114.         mov byte [STK_DESC+4],al
  115.         mov byte [STK_DESC+7],ah
  116.         
  117.         mov ax,ds
  118.         movzx eax,ax
  119.         shl eax,4
  120.         add eax,GDT_DESC
  121.         mov dword [gdtlim+2],eax
  122.         lgdt [gdtlim]
  123.         
  124.         cli
  125.         
  126.         in al,92h
  127.         or al,00000010b
  128.         out 92h,al
  129.         
  130.         mov eax,cr0
  131.         or al,1
  132.         mov cr0,eax
  133.         
  134.         jmp dword SEL_MAIN:0
  135.         
  136. real:
  137.         mov ax,cs
  138.         mov ds,ax
  139.         mov es,ax
  140.         mov ss,ax
  141.         mov sp,[RMSPValue]
  142.         
  143.         in        al, 92h
  144.         and        al, 11111101b
  145.         out        92h, al

  146.         sti

  147.         mov        ax, 4c00h
  148.         int        21h
  149.         
  150. [SECTION .s16]
  151. [BITS 16]
  152. return16:
  153.         mov ax,SEL_NORMAL
  154.         mov ds,ax
  155.         mov es,ax
  156.         mov ss,ax
  157.         mov fs,ax
  158.         mov gs,ax
  159.         
  160.         mov        eax, cr0
  161.         and        al, 11111110b
  162.         mov        cr0, eax
  163.         
  164. GoToReal:
  165.         jmp 0:real
  166.         
  167. [SECTION .main]
  168. [BITS 32]
  169. main:
  170.         mov ax,SEL_DISP
  171.         mov gs,ax
  172.         mov ax,SEL_DATA
  173.         mov ds,ax
  174.         
  175.         mov ax,SEL_TEST
  176.         mov es,ax
  177.         
  178.         mov ax,SEL_STK
  179.         mov ss,ax
  180.         mov sp,TopOfStk

  181.         mov ah,0ah
  182.         mov esi,pmmsgost
  183.         mov edi,0
  184.         cld

  185. .1:
  186.         lodsb
  187.         cmp al,0
  188.         je .2
  189.         mov [gs:edi],ax
  190.         add edi,2
  191.         jmp .1
  192.         
  193. .2:
  194.         jmp SEL_RETURN_16:0
  195.         mov ax,SEL_LDT
  196.         lldt ax
  197.         call SEL_L_CODE:0
  198. mainlen                equ        $-$
复制代码
很诡异,是不是LDT描述符和TEST描述符不能共存,一运行就崩溃

最佳答案

查看完整内容

问题的根本原因是这一句: 把这里的“equ”改成“dw”就Okay了。 下面来具体分析一下,特别是奇偶描述符个数导致有时成功/失败的原因。 首先,lgdt指令的操作数需要一个指向6字节内存区域的指针。在你的程序中,是这样做的: 遗憾的是,gdtlim是一个常数 $-$$-1,所以,DS:[gdtlim]不会在你指定的位置(GDT表的后面)。 那么,它在哪里呢? 注意,这是一个.COM文件,段寄存器DS指向程序段前缀PSP。因此,gdtlim如果 ...
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2013-1-7 21:05:43 | 显示全部楼层
问题的根本原因是这一句:
  1. gdtlim  equ $-$-1
复制代码
把这里的“equ”改成“dw”就Okay了。

下面来具体分析一下,特别是奇偶描述符个数导致有时成功/失败的原因。

首先,lgdt指令的操作数需要一个指向6字节内存区域的指针。在你的程序中,是这样做的:

  1. lgdt [gdtlim]
复制代码
遗憾的是,gdtlim是一个常数 $-$$-1,所以,DS:[gdtlim]不会在你指定的位置(GDT表的后面)。

那么,它在哪里呢?
注意,这是一个.COM文件,段寄存器DS指向程序段前缀PSP。因此,gdtlim如果不太大的话,它正好指向PSP内部。在你这个例子中,它正好位于一个非常特殊的位置,即,全零数据和非零数据的交汇处。
在这种情况下,如果描述符
  1. q:    Descriptor 0,0,0 ;一旦注释此行,就会出问题
复制代码
没有注释掉,那么gdtlim的数值会随着GDT表的尺寸增大而变大,而且正好使那6个字节中的前两个字节(GDT尺寸)为非零。所以,程序能正常工作。但是,不要得意,此时的GDT的界限值并不是正确的,而是非常大(我做过实验),只是因为非零,所以没有导致程序出错。
然而,如果注释掉那一行,那么,那么gdtlim的数值会随着GDT表的尺寸减小而变小,这正好导致那6个字节中的前两个字节(GDT尺寸)为零(因为PSP中那个地方原本就是0)。此时,执行lgdt指令后,GDT的界限值为0,进入保护模式时出现异常。
无注释时进入保护模式前的段寄存器.png
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-8 13:21:42 | 显示全部楼层
:dizzy:场外求助啊
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-1-8 21:30:01 | 显示全部楼层
是数量问题撒,换下GDT描述符数量即可- -
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-1-9 19:19:40 | 显示全部楼层
看 于渊的书呢?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-10 12:23:55 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-11 18:54:41 | 显示全部楼层
:dizzy:啊啊,求解答,或是有什么好资料推荐也好啊- -来个人吧
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-11 18:55:34 | 显示全部楼层
o70078 发表于 2013-1-8 21:30
是数量问题撒,换下GDT描述符数量即可- -

没有任何资料表示描述符数量有限制啊
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-1-11 20:24:39 | 显示全部楼层
和描述符的数量与类型没有关系。具体是出现什么问题,描述一下。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-11 23:32:52 | 显示全部楼层
本帖最后由 张国祥 于 2013-1-11 23:37 编辑
李忠 发表于 2013-1-11 20:24
和描述符的数量与类型没有关系。具体是出现什么问题,描述一下。

经过我的测试,我手动指定一个固定段基址的描述符(比如5MB处)和LDT描述符同时存在时就会引发错误,但有个神奇的地方就在于如果我再加一个空描述符在GDT内,反而不会出错,
如果再加一条,又会出错,也就是说GDT内的描述符个数为奇数时就会出错(包括首个空描述符)。
我留个源码吧,麻烦帮忙看下,谢谢。 code.zip (4.63 KB, 下载次数: 3) ,zip包含pm.inc和ldt-5m.asm两个文件
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-1-12 12:39:57 | 显示全部楼层
总有个出错位置和出错信息吧,告诉我吧。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-1-12 12:41:32 | 显示全部楼层
全是宏、EQU常量,还是COM,有点晕,你告诉我出错位置我好缩小范围。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-12 14:27:30 | 显示全部楼层
李忠 发表于 2013-1-12 12:41
全是宏、EQU常量,还是COM,有点晕,你告诉我出错位置我好缩小范围。

我没找到好的工具调试com,不过真的没有出错信息,不论是用dosbox还是虚拟机下的dos,都是直接卡住
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-12 14:29:09 | 显示全部楼层
李忠 发表于 2013-1-12 12:41
全是宏、EQU常量,还是COM,有点晕,你告诉我出错位置我好缩小范围。

出错位置就是gdt下的最后一个描述符,注释掉就会出错
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-1-12 17:43:02 | 显示全部楼层
问题的原因已经找到了。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-1-12 17:47:00 | 显示全部楼层
等朕整理一下,今晚告诉你哈。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-1-12 19:38:06 | 显示全部楼层
注意上面那幅图,这是在执行
  1. jmp dword SEL_MAIN:0
复制代码
指令前,段寄存器(包括GDTR)的内容(未加注释,程序可以正常执行的情况下)。
可以看到,DS=0xc4b0,GDT表的基地址是0xc5b4,GDT界限为0xcd00
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2013-1-12 21:42:17 | 显示全部楼层
这是gdtlim所指向的PSP内存区域映像:
无注释时进入保护模式前的PSP状态.png
注意,图中,00c5b4是你的程序写入的GDT基地址,cd00是PSP原有的内容,被误用作GDT界限值。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-12 21:43:43 | 显示全部楼层
李忠 发表于 2013-1-12 19:38
注意上面那幅图,这是在执行指令前,段寄存器(包括GDTR)的内容(未加注释,程序可以正常执行的情况下)。 ...

{:7_157:}谢谢 李老师,了解dw和equ的区别了,equ仅仅是人方便记忆和计算,,并不占用实际空间,导致lgdt实际取址时的错误。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-1-12 21:48:49 | 显示全部楼层
李忠 发表于 2013-1-12 21:42
这是gdtlim所指向的PSP内存区域映像:

注意,图中,00c5b4是你的程序写入的GDT基地址,cd00是PSP原有的内 ...

OK,了解,Bochs我还没怎么用过,我现在所学看的都是于渊老师那本书的。似乎其它适合基础较低的书很少。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-6 16:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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