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

  • 相关阅读:
    P3384 【模板】树链剖分
    AW136 邻值查找 (【模板】set)
    android布局自适应
    android HttpClient接口实现网络通信
    android加载html,以及js通讯
    mktime 和strtotime获取今日、昨日、上周、本月的起始时间戳和结束时间戳,
    mysql查询今天,昨天,近7天,近30天,本月,上一月数据方法
    瀑布流(masonry和infinitescroll)、(grid-a-licious)
    使用 JavaScript 修改浏览器 URL 地址栏
    测试UTF8编码的文件是不是加了BOM
  • 原文地址:https://www.cnblogs.com/cdwodm/p/2891167.html
Copyright © 2020-2023  润新知