2016-07-16 53 views
1

我的引导程序的这个阶段在0x7e0:0x0000加载。经过一些“调试”后,我发现下面的代码在我的远跳后会产生三重故障。如果在跳转之前移动挂起(是的,包括实际的程序本身),则不会发生三重错误。对不起,我不能包含更少的代码。我只是想确保我提供了足够的代码,以便不会错过错误。启用PMode后,远程跳闸会导致三重故障?

这里是我的代码:

bits 16 

jmp SetUpPMode 

GTDData: 
    dd 0 
    dd 0 
    ;Code Descriptor 
    dw 0xFFFF 
    dw 0 
    db 0 
    db 10011010b 
    db 11001111b 
    db 0 
    ;Data Descriptor 
    dw 0xFFFF 
    dw 0 
    db 0 
    db 10010010b 
    db 11001111b 
    db 0 
GTDEnd: 

GDTPointer: 
    dw (GTDEnd - GTDData) - 1 
    dd GTDData 

LoadGDT: 
    lgdt [GDTPointer] 
    ret 

SetUpPMode: 
    cli 
    mov ax, 0x7E0 
    mov ds, ax 

    call LoadGDT 

    mov eax, cr0 
    or eax, 1 
    mov cr0, eax 

    jmp 0x8:main 

bits 32 

main: 
    mov ax, 0x10 
    mov ds, ax 
    mov es, ax 
    mov ss, ax 
    mov esp, 0x90000 

    jmp hang 

hang: 
    ;cli 
    hlt 
    jmp hang 

我敢打赌,这个bug /错误是公然明显的,但我似乎无法找到它。有人可以指出吗? (如果它的事项,我使用虚拟盒)

+2

你应该在你的程序开始使用CLI一次,从来没有使用STI,直到你设置一个适当的保护模式IDT。在LGDT周围放置PUSHA/POPA也没有意义,因为它不会更改这些指令保存和恢复的任何寄存器。 –

+1

@RossRidge我清理了所有'sti'和'cli's,但它仍然是三重错误。我并不认为你的意见是作为答案,但我想我可能会通知你。 – DrCereal

+1

一个问题是代码中'main'的偏移量与主保护模式代码段的偏移量不匹配。在你的代码中它的偏移量就像0x00xx,但是相对于保护模式代码段它的偏移量将是0x00007exx。你或者需要调整你的代码段的基础或者你的程序的ORG(例如,所以它的加载时间是0000:7e00而不是07e0:0000) –

回答

4

您加载代码,并在0x07E0:0x0000数据。因此,汇编器和链接化妆的基础在0x07E0:0x0000的所有引用 - 如main,这可能是0x0020什么的。

但是你的GDT有基础,以0x00000000代码段 - 所以jmp 0x8:mainJMP绝对地址0x00000020什么 - 隔靴搔痒,其中代码为0x00007E20或其它地方。可以更改GDT中段的基数,也可以将代码更改为0x0000的实模式段。

+0

我用'org'和这些段稍微摆弄一下,它停止了三重错误。问题已得到解决。 – DrCereal