BackupGGCode / writeos

Write Your Own OS with Free and Open Source Software (Chinese)
1 stars 1 forks source link

实践第3章6节出现的错误 #21

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
博主,您好:
实践本书第3章6节(后面几节都出现这样问题)发现核心堆栈
错误,经过定位发现是
在这个地方出错,比如以7节例子中:
LABEL_SEG_CODE32:
    ... ...
    push    $(ARDSTitle)           /* Display addr range descriptor struct
title */
    call    DispStr
    add     $4, %esp
    call    DispAddrMap            /* Display system address map */

    call    SetupPaging            /* Setup and enable paging */

    push    $(PMMessage)
    call    DispStr
    add     $4, %esp
    ... ...
把上面的代码屏蔽掉则不会出现问题。
我使用的编译系统环境是:redhat AS 4.6,内置gcc 
3.4.6,实践的BOCHS版本为2.3。

在WIN2003下使用BOCHSGDB.EXE调试,出现下面这种情况:
00000000000i[APIC?] local apic in  initializing
========================================================================
                        Bochs x86 Emulator 2.3
              Build from CVS snapshot on August 27, 2006
========================================================================
00000000000i[     ] reading configuration from bochsrc.bxrc
00000000000i[     ] WARNING: syntax has changed, please use 'vgaromimage:
file=...' now
00000000000i[     ] installing win32 module as the Bochs GUI
00000000000i[     ] using log file bochsout.txt
Next at t=0
(0) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b         ; ea5be000f0
<bochs:1> vb 0x0008:0x00000000
<bochs:2> c
(7563480) Breakpoint 0, in 0008:00000000 (0x00090922)
Next at t=8830245
(0) [0x00090922] 0008:00000000 (unk. ctxt): mov ax, 0x0010            ;
66b81000
<bochs:3> u /12
00090922: (                    ): mov ax, 0x0010            ; 66b81000
00090926: (                    ): mov ds, ax                ; 8ed8
00090928: (                    ): mov ax, 0x0010            ; 66b81000
0009092c: (                    ): mov es, ax                ; 8ec0
0009092e: (                    ): mov ax, 0x0018            ; 66b81800
00090932: (                    ): mov ss, ax                ; 8ed0
00090934: (                    ): mov ax, 0x0020            ; 66b82000
00090938: (                    ): mov gs, ax                ; 8ee8
0009093a: (                    ): mov esp, 0x00000200       ; bc00020000
0009093f: (                    ): push 0x00000043           ; 6a43
00090941: (                    ): call .+0x000002ae         ; e8ae020000
00090946: (                    ): add esp, 0x00000004       ; 83c404
<bochs:4> pb 0x00090941
<bochs:5> c
(0) Breakpoint 2, 0x00090941 in ?? ()
Next at t=8830255
(0) [0x00090941] 0008:0000001f (unk. ctxt): call .+0x000002ae (0x00090bf4)
; e8ae020000
<bochs:6> s
Next at t=8830255
(0) [0x00090941] 0008:001f (unk. ctxt): call .+0x000002ae (0xffff02d2) ;
e8ae020000
<bochs:7> s
Next at t=8830256
(0) [0x000fe05b] f000:e05b (unk. ctxt): xor ax, ax                ; 31c0
<bochs:8> u /16
000fe05b: (                    ): xor ax, ax                ; 31c0
000fe05d: (                    ): out 0x0d, al              ; e60d
000fe05f: (                    ): out 0xda, al              ; e6da
000fe061: (                    ): mov al, 0xc0              ; b0c0
000fe063: (                    ): out 0xd6, al              ; e6d6
000fe065: (                    ): mov al, 0x00              ; b000
000fe067: (                    ): out 0xd4, al              ; e6d4
000fe069: (                    ): mov al, 0x0f              ; b00f
000fe06b: (                    ): out 0x70, al              ; e670
000fe06d: (                    ): in al, 0x71               ; e471
000fe06f: (                    ): mov bl, al                ; 88c3
000fe071: (                    ): mov al, 0x0f              ; b00f
000fe073: (                    ): out 0x70, al              ; e670
000fe075: (                    ): mov al, 0x00              ; b000
000fe077: (                    ): out 0x71, al              ; e671
000fe079: (                    ): mov al, bl                ; 88d8
<bochs:9>
因为最近在学习这些东西,很多不太明白,请博主及明白原��
�的同学告知。

Original issue reported on code.google.com by roaph...@gmail.com on 1 Jun 2009 at 6:06

GoogleCodeExporter commented 9 years ago
在执行call    DispAddrMap这条指令(即[0x00090941] 0008:0000001f (unk. 
ctxt): call
.+0x000002ae (0x00090bf4)),GDTR设置如下:
<bochs:6> dump_cpu
eax:0x00000020, ebx:0x00000000, ecx:0x00000014, edx:0x534d4150
ebp:0x00007d29, esp:0x000001fc, esi:0x00007d1f, edi:0x00000280
eip:0x0000001f, eflags:0x00000006, inhibit_mask:0
cs:s=0x0008, dl=0x0922005b, dh=0x00409a09, valid=1
ss:s=0x0018, dl=0x031c0200, dh=0x00409309, valid=5
ds:s=0x0010, dl=0x017901a2, dh=0x00009209, valid=1
es:s=0x0010, dl=0x017901a2, dh=0x00009309, valid=1
fs:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
gs:s=0x0020, dl=0x8000ffff, dh=0x0000f20b, valid=1
ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
tr:s=0x0000, dl=0x0000ffff, dh=0x00008300, valid=1
gdtr:base=0x00090103, limit=0x67
idtr:base=0x00000000, limit=0xffff
dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
dr3:0x00000000, dr6:0xffff0ff0, dr7:0x00000400
cr0:0x00000011, cr1:0x00000000, cr2:0x00000000
cr3:0x00000000, cr4:0x00000000
done

Original comment by roaph...@gmail.com on 2 Jun 2009 at 2:45

GoogleCodeExporter commented 9 years ago
堆栈显示:
Stack address size 4
 | STACK 0x000001fc [0xf000ff53]
 | STACK 0x00000200 [0xf000ff53]
 | STACK 0x00000204 [0xf000ff53]
 | STACK 0x00000208 [0xf000ff53]
 | STACK 0x0000020c [0xf000ff53]
 | STACK 0x00000210 [0xf000ff53]
 | STACK 0x00000214 [0xf000ff53]
 | STACK 0x00000218 [0xf000ff53]
 | STACK 0x0000021c [0xf000ff53]
 | STACK 0x00000220 [0xf000ff53]
 | STACK 0x00000224 [0xf000ff53]
 | STACK 0x00000228 [0xf000ff53]
 | STACK 0x0000022c [0xf000ff53]
 | STACK 0x00000230 [0xf000ff53]
 | STACK 0x00000234 [0xf000ff53]
 | STACK 0x00000238 [0xf000ff53]

Original comment by roaph...@gmail.com on 2 Jun 2009 at 2:55

GoogleCodeExporter commented 9 years ago
对照于渊的《自己动手写操作系统》提供的源代码,另外根��
�自己环境,做出了修改,问题解决了。
比如第3章6节的代码修改如下:

/* chapter3/6/loader.S

   Author: Wenbo Yang <solrex@gmail.com> <http://solrex.cn>

   This file is part of the source code of book "Write Your Own OS with Free
   and Open Source Software". Homepage @ <http://share.solrex.cn/WriteOS/>.

   This file is licensed under the GNU General Public License; either
   version 3 of the License, or (at your option) any later version. */

/* 此处把原来的 包含方式修改了 */
/* #include "pm.h" */
.include "pm.h"

.set    PageDirBase, 0x200000   /* 2MB, base address of page directory */
.set    PageTblBase, 0x201000   /* 2MB+4KB, base address of page table */

.code16
.text
    jmp LABEL_BEGIN     /* jump over the .data section. */

/* NOTE! Wenbo-20080512: Actually here we put the normal .data section into
   the .code section. For application SW, it is not allowed. However, we are
   writing an OS. That is OK. Because there is no OS to complain about
   that behavior. :) */

/* 
此处做了修改,可能是编译器对宏汇编处理的问题,比如之��
�为:(SegCode32Len - 1)
   现在修改为: (SegCode32Len-1), 即括号内的内容需要紧促, 下面几处同此 */
/* Global Descriptor Table */
LABEL_GDT:          Descriptor        0,                  0, 0
LABEL_DESC_CODE32:  Descriptor        0,    (SegCode32Len-1), (DA_C+DA_32)
LABEL_DESC_DATA:    Descriptor        0,        (DataLen-1), DA_DRW
LABEL_DESC_STACK:   Descriptor        0,         TopOfStack, (DA_DRWA+DA_32)
LABEL_DESC_VIDEO:   Descriptor  0xB8000,             0xffff, (DA_DRW+DA_DPL3)
LABEL_DESC_LDT:     Descriptor        0,       (LDTLen-1), DA_LDT
LABEL_DESC_CODECG:  Descriptor        0, (SegCodeCGLen-1), (DA_C+DA_32)
LABEL_DESC_CODER3:  Descriptor        0, (SegCodeR3Len-1), (DA_C+DA_32+DA_DPL3)
LABEL_DESC_STACKR3: Descriptor        0,       TopOfStackR3, 
(DA_DRWA+DA_32+DA_DPL3)
LABEL_DESC_TSS:     Descriptor        0,       (TSSLen-1), DA_386TSS
LABEL_DESC_PAGEDIR: Descriptor PageDirBase,            4096, DA_DRW
LABEL_DESC_PAGETBL: Descriptor PageTblBase,            1023, 
(DA_DRW|DA_LIMIT_4K) /*4M*/
/* Gate Descriptors */
LABEL_CG_TEST:      Gate    SelectorCodeCG, 0, 0, (DA_386CGate + DA_DPL3)

.set GdtLen, (. - LABEL_GDT)  /* GDT Length */

GdtPtr: .2byte  (GdtLen - 1)  /* GDT Limit */
        .4byte  0             /* GDT Base */

/* GDT Selector(TI flag clear) */
.set    SelectorCode32, (LABEL_DESC_CODE32 - LABEL_GDT)
.set    SelectorData,   (LABEL_DESC_DATA   - LABEL_GDT)
.set    SelectorStack,  (LABEL_DESC_STACK  - LABEL_GDT)
.set    SelectorVideo,  (LABEL_DESC_VIDEO  - LABEL_GDT)
.set    SelectorLDT,    (LABEL_DESC_LDT    - LABEL_GDT)
.set    SelectorCodeCG, (LABEL_DESC_CODECG - LABEL_GDT)
.set    SelectorCGTest, (LABEL_CG_TEST     - LABEL_GDT)
.set    SelectorCodeR3, (LABEL_DESC_CODER3 - LABEL_GDT + SA_RPL3)
.set    SelectorStackR3,(LABEL_DESC_STACKR3- LABEL_GDT + SA_RPL3)
.set    SelectorTSS,    (LABEL_DESC_TSS - LABEL_GDT)
.set    SelectorPageDir,(LABEL_DESC_PAGEDIR - LABEL_GDT)
.set    SelectorPageTbl,(LABEL_DESC_PAGETBL - LABEL_GDT)

/* LDT segment */
LABEL_LDT:
LABEL_LDT_DESC_CODEA:   Descriptor  0, (CodeALen-1), (DA_C+DA_32)

.set    LDTLen, (. - LABEL_LDT) /* LDT Length */
/* LDT Selector (TI flag set)*/
.set    SelectorLDTCodeA, (LABEL_LDT_DESC_CODEA - LABEL_LDT + SA_TIL)

/* 32-bit global data segment. */
LABEL_DATA:
PMMessage:   .ascii "Welcome to protect mode! ^-^\0"
LDTMessage:  .ascii "Aha, you jumped into a LDT segment.\0"
.set    OffsetPMMessage,  (PMMessage - LABEL_DATA)
.set    OffsetLDTMessage, (LDTMessage - LABEL_DATA)
.set    DataLen,          (. - LABEL_DATA)

/* 32-bit global stack segment. */
.align  4
LABEL_STACK:
.space  512, 0
.set    TopOfStack, (. - LABEL_STACK)

/* 32-bit ring 3 stack segment. */
LABEL_STACKR3:
.space  512, 0
.set    TopOfStackR3, (. - LABEL_STACKR3)

LABEL_TSS:
    .4byte  0           /* Back Link */
    .4byte  TopOfStack  /* ESP0 */
    .4byte  SelectorStack /* SS0 */
    .4byte  0           /* ESP1 */
    .4byte  0           /* SS1 */
    .4byte  0           /* ESP2 */
    .4byte  0           /* SS2 */
    .4byte  0           /* CR3(PDBR) */
    .4byte  0           /* EIP */
    .4byte  0           /* EFLAGS */
    .4byte  0           /* EAX */
    .4byte  0           /* ECX */
    .4byte  0           /* EDX */
    .4byte  0           /* EBX */
    .4byte  0           /* ESP */
    .4byte  0           /* EBP */
    .4byte  0           /* ESI */
    .4byte  0           /* EDI */
    .4byte  0           /* ES */
    .4byte  0           /* CS */
    .4byte  0           /* SS */
    .4byte  0           /* DS */
    .4byte  0           /* FS */
    .4byte  0           /* GS */
    .4byte  0           /* LDT Segment Selector */
    .2byte  0           /* Trap Flag: 1-bit */
    .2byte  (. - LABEL_TSS + 2)     /* I/O Map Base Address */
    .byte   0xff        /* End */
.set    TSSLen, (. - LABEL_TSS)

/* Program starts here. */
LABEL_BEGIN:
    mov     %cs, %ax    /* Move code segment address(CS) to data segment */
    mov     %ax, %ds    /* register(DS), ES and SS. Because we have      */
    mov     %ax, %es    /* embedded .data section into .code section in  */
    mov     %ax, %ss    /* the start(mentioned in the NOTE above).        */

    mov     $0x100, %sp

    /* Initialize 32-bits code segment descriptor. */
    InitDesc LABEL_SEG_CODE32, LABEL_DESC_CODE32

    /* Initialize data segment descriptor. */
    InitDesc LABEL_DATA, LABEL_DESC_DATA

    /* Initialize stack segment descriptor. */
    InitDesc LABEL_STACK, LABEL_DESC_STACK

    /* Initialize LDT descriptor in GDT. */
    InitDesc LABEL_LDT, LABEL_DESC_LDT

    /* Initialize code A descriptor in LDT. */
    InitDesc LABEL_CODEA, LABEL_LDT_DESC_CODEA

    /* Initialize call gate dest code segment descriptor. */
    InitDesc LABEL_SEG_CODECG, LABEL_DESC_CODECG

    /* Initialize ring 3 stack segment descriptor. */
    InitDesc LABEL_STACKR3, LABEL_DESC_STACKR3

    /* Initialize ring 3 dest code segment descriptor. */
    InitDesc LABEL_SEG_CODER3, LABEL_DESC_CODER3

    /* Initialize TSS segment descriptor. */
    InitDesc LABEL_TSS, LABEL_DESC_TSS

    /* Prepared for loading GDTR */
    xor     %eax, %eax
    mov     %ds, %ax
    shl     $4, %eax
    add     $(LABEL_GDT), %eax      /* eax <- gdt base*/
    movl    %eax, (GdtPtr + 2)

    /* Load GDTR(Global Descriptor Table Register) */
    lgdtw   GdtPtr

    /* Clear Interrupt Flags */
    cli

    /* Open A20 line. */
    inb     $0x92, %al
    orb     $0b00000010, %al
    outb    %al, $0x92

    /* Enable protect mode, PE bit of CR0. */
    movl    %cr0, %eax
    orl     $1, %eax
    movl    %eax, %cr0

    /* Mixed-Size Jump. */
    ljmpl $SelectorCode32, $0       /* Thanks to earthengine@gmail, I got */
                                    /* this mixed-size jump insn of gas.  */

/* 32-bit code segment for LDT */
LABEL_CODEA:
.code32
    mov     $(SelectorVideo), %ax
    mov     %ax, %gs

    movb    $0xC, %ah               /* 0000: Black Back 1100: Red Front */
    xor     %esi, %esi
    xor     %edi, %edi
    movl    $(OffsetLDTMessage), %esi
    movl    $((80 * 12 + 0) * 2), %edi
    cld                         /* Clear DF flag. */

/* Display a string from %esi(string offset) to %edi(video segment). */
CODEA.1:
    lodsb                       /* Load a byte from source */
    test    %al, %al
    jz      CODEA.2
    mov     %ax, %gs:(%edi)
    add     $2, %edi
    jmp     CODEA.1
CODEA.2:

    /* Stop here, infinite loop. */
    jmp     .
.set    CodeALen, (. - LABEL_CODEA)

/* 32-bit code segment for call gate destination segment */
LABEL_SEG_CODECG:
    mov     $(SelectorVideo), %ax
    mov     %ax, %gs

    movl    $((80 * 11 + 0) * 2), %edi  /* line 11, column 0 */
    movb    $0xC, %ah               /* 0000: Black Back 1100: Red Front */
    movb    $'C', %al               /* Print a 'C' */

    mov     %ax, %gs:(%edi)
    lret

/* Get the length of 32-bit call gate destination segment code. */
.set    SegCodeCGLen, . - LABEL_SEG_CODECG

/* 32-bit code segment for running in ring 3. */
LABEL_SEG_CODER3:
    mov     $(SelectorVideo), %ax
    mov     %ax, %gs

    movl    $((80 * 11 + 1) * 2), %edi  /* line 11, column 1 */
    movb    $0xC, %ah               /* 0000: Black Back 1100: Red Front */
    movb    $'3', %al               /* Print a '3' */

    mov     %ax, %gs:(%edi)
    lcall   $(SelectorCGTest), $0  /* Call CODECG through call gate */
    jmp     .   

/* Get the length of 32-bit ring 3 segment code. */
.set    SegCodeR3Len, . - LABEL_SEG_CODER3

/* 32-bit code segment for GDT */
LABEL_SEG_CODE32: 
    call    SetupPaging     /* set up paging before 32-bit code */

    mov     $(SelectorData), %ax
    mov     %ax, %ds                /* Data segment selector */
    mov     $(SelectorStack), %ax
    mov     %ax, %ss                /* Stack segment selector */
    mov     $(SelectorVideo), %ax
    mov     %ax, %gs                /* Video segment selector(dest) */

    mov     $(TopOfStack), %esp

    movb    $0xC, %ah               /* 0000: Black Back 1100: Red Front */
    xor     %esi, %esi
    xor     %edi, %edi
    movl    $(OffsetPMMessage), %esi
    movl    $((80 * 10 + 0) * 2), %edi
    cld                         /* Clear DF flag. */

/* Display a string from %esi(string offset) to %edi(video segment). */
CODE32.1:
    lodsb                       /* Load a byte from source */
    test    %al, %al
    jz      CODE32.2
    mov     %ax, %gs:(%edi)
    add     $2, %edi
    jmp     CODE32.1
CODE32.2:

    mov     $(SelectorTSS), %ax    /* Load TSS to TR register */
    ltr     %ax

    pushl   $(SelectorStackR3)     /* Fake call procedure. */
    pushl   $(TopOfStackR3)
    pushl   $(SelectorCodeR3)
    pushl   $0
    lret                           /* return with no call */

CODE32.3:
    mov     $(SelectorLDT), %ax
    lldt    %ax

    ljmp    $(SelectorLDTCodeA), $0

/* Get the length of 32-bit segment code. */
/* 此处做了修改 因为下面的SetupPaging也应该是32位代码 */
/*.set    SegCode32Len, . - LABEL_SEG_CODE32 */

SetupPaging:
/* Directly map linear addresses to physical addresses for simplification */
    /* Init page directory, %ecx entries. */
    mov     $(SelectorPageDir), %ax
    mov     %ax, %es
    mov     $1024, %ecx     /* Loop counter, num of page tables: 1024 */
    xor     %edi, %edi
    xor     %eax, %eax
    /* Set PDE attributes(flags): P: 1, U/S: 1, R/W: 1. */
    mov     $(PageTblBase | PG_P | PG_USU | PG_RWW), %eax
SP.1:
    stosl                   /* Store %eax to %es:%edi consecutively. */
    add     $4096, %eax     /* Page tables are in sequential format. */
    loop    SP.1            /* %ecx loops. */

    /* Init page tables, %ecx pages. */
    mov     $(SelectorPageTbl), %ax
    mov     %ax, %es
    mov     $(1024*1024), %ecx  /* Loop counter, num of pages: 1024^2. */
    xor     %edi, %edi
    /* Set PTE attributes(flags): P:1, U/S: 1锛?R/W: 1. */
    mov     $(PG_P | PG_USU | PG_RWW), %eax
SP.2:
    stosl                   /* Store %eax to %es:%edi consecutively. */
    add     $4096, %eax     /* Pages are in sequential format. */
    loop    SP.2            /* %ecx loops. */

    mov     $(PageDirBase), %eax
    mov     %eax, %cr3  /* Store base address of page table dir to %cr3. */
    mov     %cr0, %eax
    or      $0x80000000, %eax
    mov     %eax, %cr0  /* Enable paging bit in %cr0. */
    ret

/* 此处做了移动 */   
.set    SegCode32Len, . - LABEL_SEG_CODE32

Original comment by roaph...@gmail.com on 2 Jun 2009 at 4:43

GoogleCodeExporter commented 9 years ago
我也碰到了同样的问题,原来的代码在执行call 
SetupPaging时会超过段限制

Original comment by yangdk.cn@gmail.com on 12 Dec 2010 at 11:42