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的差别在那

你可能感兴趣的:(test)