pmtest7错误探索

先说下我配的环境,msdos622,vpc2007,当我在执行pmtest7的时候,崩溃,无法执行,在此之后,我又通过bochs配置了环境,可以调试.com程序(见上一篇博客),调试了良久(不太会调试,bochs有些调试还是不会)模模糊糊知道是哪错了,我在下面帖出来,还请高手指正

  1 ; ==========================================
  2 ; pmtest7.asm
  3 ; 编译方法:nasm pmtest7.asm -o pmtest7.com
  4 ; ==========================================
  5 
  6 %include    "pm.inc"    ; 常量, 宏, 以及一些说明
  7 
  8 PageDirBase        equ    200000h    ; 页目录开始地址:    2M
  9 PageTblBase        equ    201000h    ; 页表开始地址:        2M + 4K
 10 
 11 org    0100h
 12     jmp    LABEL_BEGIN
 13 
 14 [SECTION .gdt]
 15 ; GDT
 16 ;                                         段基址,       段界限     , 属性
 17 LABEL_GDT:        Descriptor           0,                 0, 0            ; 空描述符
 18 LABEL_DESC_NORMAL:    Descriptor           0,            0ffffh, DA_DRW        ; Normal 描述符
 19 LABEL_DESC_PAGE_DIR:    Descriptor   PageDirBase,              4095, DA_DRW        ; Page Directory
 20 LABEL_DESC_PAGE_TBL:    Descriptor   PageTblBase,      4096 * 8 - 1, DA_DRW        ; Page Tables
 21 LABEL_DESC_CODE32:    Descriptor           0,  SegCode32Len - 1, DA_C + DA_32    ; 非一致代码段, 32
 22 LABEL_DESC_CODE16:    Descriptor           0,            0ffffh, DA_C        ; 非一致代码段, 16
 23 LABEL_DESC_DATA:    Descriptor           0,    DataLen - 1, DA_DRW        ; Data
 24 LABEL_DESC_STACK:    Descriptor           0,        TopOfStack, DA_DRWA + DA_32    ; Stack, 32 位
 25 LABEL_DESC_VIDEO:    Descriptor     0B8000h,            0ffffh, DA_DRW        ; 显存首地址
 26 ; GDT 结束
 27 
 28 GdtLen        equ    $ - LABEL_GDT    ; GDT长度
 29 GdtPtr        dw    GdtLen - 1    ; GDT界限
 30         dd    0        ; GDT基地址
 31 
 32 ; GDT 选择子
 33 SelectorNormal        equ    LABEL_DESC_NORMAL    - LABEL_GDT
 34 SelectorPageDir        equ    LABEL_DESC_PAGE_DIR    - LABEL_GDT
 35 SelectorPageTbl        equ    LABEL_DESC_PAGE_TBL    - LABEL_GDT
 36 SelectorCode32        equ    LABEL_DESC_CODE32    - LABEL_GDT
 37 SelectorCode16        equ    LABEL_DESC_CODE16    - LABEL_GDT
 38 SelectorData        equ    LABEL_DESC_DATA        - LABEL_GDT
 39 SelectorStack        equ    LABEL_DESC_STACK    - LABEL_GDT
 40 SelectorVideo        equ    LABEL_DESC_VIDEO    - LABEL_GDT
 41 ; END of [SECTION .gdt]
 42 
 43 [SECTION .data1]     ; 数据段
 44 ALIGN    32
 45 [BITS    32]
 46 LABEL_DATA:
 47 ; 实模式下使用这些符号
 48 ; 字符串
 49 _szPMMessage:            db    "In Protect Mode now. ^-^", 0Ah, 0Ah, 0    ; 进入保护模式后显示此字符串
 50 _szMemChkTitle:            db    "BaseAddrL BaseAddrH LengthLow LengthHigh   Type", 0Ah, 0    ; 进入保护模式后显示此字符串
 51 _szRAMSize            db    "RAM size:", 0
 52 _szReturn            db    0Ah, 0
 53 ; 变量
 54 _wSPValueInRealMode        dw    0
 55 _dwMCRNumber:            dd    0    ; Memory Check Result
 56 _dwDispPos:            dd    (80 * 6 + 0) * 2    ; 屏幕第 6 行, 第 0 列。
 57 _dwMemSize:            dd    0
 58 _ARDStruct:            ; Address Range Descriptor Structure
 59     _dwBaseAddrLow:        dd    0
 60     _dwBaseAddrHigh:    dd    0
 61     _dwLengthLow:        dd    0
 62     _dwLengthHigh:        dd    0
 63     _dwType:        dd    0
 64 
 65 _MemChkBuf:    times    256    db    0
 66 
 67 ; 保护模式下使用这些符号
 68 szPMMessage        equ    _szPMMessage    - $$
 69 szMemChkTitle    equ    _szMemChkTitle    - $$
 70 szRAMSize        equ    _szRAMSize    - $$
 71 szReturn        equ    _szReturn    - $$
 72 dwDispPos        equ    _dwDispPos    - $$
 73 dwMemSize        equ    _dwMemSize    - $$
 74 dwMCRNumber        equ    _dwMCRNumber    - $$
 75 ARDStruct        equ    _ARDStruct    - $$
 76     dwBaseAddrLow    equ    _dwBaseAddrLow    - $$
 77     dwBaseAddrHigh    equ    _dwBaseAddrHigh    - $$
 78     dwLengthLow    equ    _dwLengthLow    - $$
 79     dwLengthHigh    equ    _dwLengthHigh    - $$
 80     dwType        equ    _dwType        - $$
 81 MemChkBuf        equ    _MemChkBuf    - $$
 82 
 83 DataLen            equ    $ - LABEL_DATA
 84 ; END of [SECTION .data1]
 85 
 86 
 87 ; 全局堆栈段
 88 [SECTION .gs]
 89 ALIGN    32
 90 [BITS    32]
 91 LABEL_STACK:
 92     times 512 db 0
 93 
 94 TopOfStack    equ    $ - LABEL_STACK - 1
 95 
 96 ; END of [SECTION .gs]
 97 
 98 
 99 [SECTION .s16]
100 [BITS    16]
101 LABEL_BEGIN:
102     mov    ax, cs
103     mov    ds, ax
104     mov    es, ax
105     mov    ss, ax
106     mov    sp, 0100h
107 
108     mov    [LABEL_GO_BACK_TO_REAL+3], ax
109     mov    [_wSPValueInRealMode], sp
110 
111     ; 得到内存数
112     mov    ebx, 0
113     mov    di, _MemChkBuf
114 .loop:
115     mov    eax, 0E820h
116     mov    ecx, 20
117     mov    edx, 0534D4150h
118     int    15h
119     jc    LABEL_MEM_CHK_FAIL
120     add    di, 20
121     inc    dword [_dwMCRNumber]
122     cmp    ebx, 0
123     jne    .loop
124     jmp    LABEL_MEM_CHK_OK
125 LABEL_MEM_CHK_FAIL:
126     mov    dword [_dwMCRNumber], 0
127 LABEL_MEM_CHK_OK:
128 
129     ; 初始化 16 位代码段描述符
130     mov    ax, cs
131     movzx    eax, ax
132     shl    eax, 4
133     add    eax, LABEL_SEG_CODE16
134     mov    word [LABEL_DESC_CODE16 + 2], ax
135     shr    eax, 16
136     mov    byte [LABEL_DESC_CODE16 + 4], al
137     mov    byte [LABEL_DESC_CODE16 + 7], ah
138 
139     ; 初始化 32 位代码段描述符
140     xor    eax, eax
141     mov    ax, cs
142     shl    eax, 4
143     add    eax, LABEL_SEG_CODE32
144     mov    word [LABEL_DESC_CODE32 + 2], ax
145     shr    eax, 16
146     mov    byte [LABEL_DESC_CODE32 + 4], al
147     mov    byte [LABEL_DESC_CODE32 + 7], ah
148 
149     ; 初始化数据段描述符
150     xor    eax, eax
151     mov    ax, ds
152     shl    eax, 4
153     add    eax, LABEL_DATA
154     mov    word [LABEL_DESC_DATA + 2], ax
155     shr    eax, 16
156     mov    byte [LABEL_DESC_DATA + 4], al
157     mov    byte [LABEL_DESC_DATA + 7], ah
158 
159     ; 初始化堆栈段描述符
160     xor    eax, eax
161     mov    ax, ds
162     shl    eax, 4
163     add    eax, LABEL_STACK
164     mov    word [LABEL_DESC_STACK + 2], ax
165     shr    eax, 16
166     mov    byte [LABEL_DESC_STACK + 4], al
167     mov    byte [LABEL_DESC_STACK + 7], ah
168 
169     ; 为加载 GDTR 作准备
170     xor    eax, eax
171     mov    ax, ds
172     shl    eax, 4
173     add    eax, LABEL_GDT        ; eax <- gdt 基地址
174     mov    dword [GdtPtr + 2], eax    ; [GdtPtr + 2] <- gdt 基地址
175 
176     ; 加载 GDTR
177     lgdt    [GdtPtr]
178 
179     ; 关中断
180     cli
181 
182     ; 打开地址线A20
183     in    al, 92h
184     or    al, 00000010b
185     out    92h, al
186 
187     ; 准备切换到保护模式
188     mov    eax, cr0
189     or    eax, 1
190     mov    cr0, eax
191 
192     ; 真正进入保护模式
193     jmp    dword SelectorCode32:0    ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:0  处
194 
195 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
196 
197 LABEL_REAL_ENTRY:        ; 从保护模式跳回到实模式就到了这里
198     mov    ax, cs
199     mov    ds, ax
200     mov    es, ax
201     mov    ss, ax
202 
203     mov    sp, [_wSPValueInRealMode]
204 
205     in    al, 92h        ;
206     and    al, 11111101b    ; ┣ 关闭 A20 地址线
207     out    92h, al        ;
208 
209     sti            ; 开中断
210 
211     mov    ax, 4c00h    ;
212     int    21h        ; ┛回到 DOS
213 ; END of [SECTION .s16]
214 
215 
216 [SECTION .s32]; 32 位代码段. 由实模式跳入.
217 [BITS    32]
218 
219 LABEL_SEG_CODE32:
220     mov    ax, SelectorData
221     mov    ds, ax            ; 数据段选择子
222     mov    ax, SelectorData
223     mov    es, ax
224     mov    ax, SelectorVideo
225     mov    gs, ax            ; 视频段选择子
226 
227     mov    ax, SelectorStack
228     mov    ss, ax            ; 堆栈段选择子
229 
230     mov    esp, TopOfStack
231 
232 
233     ; 下面显示一个字符串
234     push    szPMMessage
235     call    DispStr
236     add    esp, 4
237 
238     push    szMemChkTitle
239     call    DispStr
240     add    esp, 4
241 
242     ;call    DispMemSize        ; 显示内存信息
243 
244     call    SetupPaging        ; 启动分页机制
245 
246     ; 到此停止
247     jmp    SelectorCode16:0
248 
249 ; 启动分页机制 --------------------------------------------------------------
250 SetupPaging:
251     ; 根据内存大小计算应初始化多少PDE以及多少页表
252     xor    edx, edx
253     mov    eax, [dwMemSize]
254     mov    ebx, 400000h    ; 400000h = 4M = 4096 * 1024, 一个页表对应的内存大小
255     div    ebx
256     mov    ecx, eax    ; 此时 ecx 为页表的个数,也即 PDE 应该的个数
257     test    edx, edx
258     jz    .no_remainder
259     inc    ecx        ; 如果余数不为 0 就需增加一个页表
260 .no_remainder:
261     push    ecx        ; 暂存页表个数
262 
263     ; 为简化处理, 所有线性地址对应相等的物理地址. 并且不考虑内存空洞.
264 
265     ; 首先初始化页目录
266     mov    ax, SelectorPageDir    ; 此段首地址为 PageDirBase
267     mov    es, ax
268     xor    edi, edi
269     xor    eax, eax
270     mov    eax, PageTblBase | PG_P  | PG_USU | PG_RWW
271 .1:
272     stosd
273     add    eax, 4096        ; 为了简化, 所有页表在内存中是连续的.
274     loop    .1
275 
276     ; 再初始化所有页表
277     mov    ax, SelectorPageTbl    ; 此段首地址为 PageTblBase
278     mov    es, ax
279     pop    eax            ; 页表个数
280     mov    ebx, 1024        ; 每个页表 1024 个 PTE
281     mul    ebx
282     mov    ecx, eax        ; PTE个数 = 页表个数 * 1024,,,,,这个地方我感觉错了,调试的时候发我先ecx=2000h,我把这个地方ecx直接赋值为2000h是可以执行的,还有这里的mul我感觉是错的,32位乘32位最后结果保存在edx和eax中,虽然在调试的时候发现edx是0,但是这里我还是不建议这么写。
283     xor    edi, edi
284     xor    eax, eax
285     mov    eax, PG_P  | PG_USU | PG_RWW
286 .2:
287     stosd
288     add    eax, 4096        ; 每一页指向 4K 的空间
289     loop    .2
290 
291     mov    eax, PageDirBase
292     mov    cr3, eax
293     mov    eax, cr0
294     or    eax, 80000000h
295     mov    cr0, eax
296     jmp    short .3
297 .3:
298     nop
299 
300     ret
301 ; 分页机制启动完毕 ----------------------------------------------------------
302 
303 
304 
305 DispMemSize:
306     push    esi
307     push    edi
308     push    ecx
309 
310     mov    esi, MemChkBuf
311     mov    ecx, [dwMCRNumber]    ;for(int i=0;i<[MCRNumber];i++) // 每次得到一个ARDS(Address Range Descriptor Structure)结构
312 .loop:                    ;{
313     mov    edx, 5            ;    for(int j=0;j<5;j++)    // 每次得到一个ARDS中的成员,共5个成员
314     mov    edi, ARDStruct        ;    {            // 依次显示:BaseAddrLow,BaseAddrHigh,LengthLow,LengthHigh,Type
315 .1:                    ;
316     push    dword [esi]        ;
317     call    DispInt            ;        DispInt(MemChkBuf[j*4]); // 显示一个成员
318     pop    eax            ;
319     stosd                ;        ARDStruct[j*4] = MemChkBuf[j*4];
320     add    esi, 4            ;
321     dec    edx            ;
322     cmp    edx, 0            ;
323     jnz    .1            ;    }
324     call    DispReturn        ;    printf("\n");
325     cmp    dword [dwType], 1    ;    if(Type == AddressRangeMemory) // AddressRangeMemory : 1, AddressRangeReserved : 2
326     jne    .2            ;    {
327     mov    eax, [dwBaseAddrLow]    ;
328     add    eax, [dwLengthLow]    ;
329     cmp    eax, [dwMemSize]    ;        if(BaseAddrLow + LengthLow > MemSize)
330     jb    .2            ;
331     mov    [dwMemSize], eax    ;            MemSize = BaseAddrLow + LengthLow;
332 .2:                    ;    }
333     loop    .loop            ;}
334                     ;
335     call    DispReturn        ;printf("\n");
336     push    szRAMSize        ;
337     call    DispStr            ;printf("RAM size:");
338     add    esp, 4            ;
339                     ;
340     push    dword [dwMemSize]    ;
341     call    DispInt            ;DispInt(MemSize);
342     add    esp, 4            ;
343 
344     pop    ecx
345     pop    edi
346     pop    esi
347     ret
348 
349 %include    "lib.inc"    ; 库函数
350 
351 SegCode32Len    equ    $ - LABEL_SEG_CODE32
352 ; END of [SECTION .s32]
353 
354 
355 ; 16 位代码段. 由 32 位代码段跳入, 跳出后到实模式
356 [SECTION .s16code]
357 ALIGN    32
358 [BITS    16]
359 LABEL_SEG_CODE16:
360     ; 跳回实模式:
361     mov    ax, SelectorNormal
362     mov    ds, ax
363     mov    es, ax
364     mov    fs, ax
365     mov    gs, ax
366     mov    ss, ax
367 
368     mov    eax, cr0
369     and    al, 11111110b
370     mov    cr0, eax
371 
372 LABEL_GO_BACK_TO_REAL:
373     jmp    0:LABEL_REAL_ENTRY    ; 段地址会在程序开始处被设置成正确的值
374 
375 Code16Len    equ    $ - LABEL_SEG_CODE16
376 
377 ; END of [SECTION .s16code]

我看的书是自己动手第一版,但是在无意中我看到了第二版光盘中的资料里面有可用的freedos,于是拿来一试,结果pmtest7是可以运行的,顿时感觉我被环境坑了两天,不过这两天琢磨琢磨这,琢磨琢磨那总算是学到不少东西,就是进度慢了

建议大家学的时候用freedos吧,虽然不知道这和msdos的差别在那

原文地址:https://www.cnblogs.com/cdwodm/p/2891167.html