2016-05-04 2 views
1

の原因となります。私のGDTには3つのエントリがあります。私はIDTを作成し、ISRとIQRを実装しました。私はまたPICを再マッピングしました。問題は、すべての割り込みハンドラが一般保護違反の後に続くことです。 これは、割り込みを呼び出すアセンブリコードです:すべてのIRQとISRは、私は、オペレーティング・システムを開発していますGPF

.extern fault_handler 
isr_common_stub: 
    pusha 
    push %ds 
    push %es 
    push %fs 
    push %gs 
    movw $0x10,%ax # Load the Kernel Data Segment descriptor! 
    movw %ax,%ds 
    movw %ax,%es 
    movw %ax,%fs 
    movw %ax,%gs 
    movl %esp,%eax # Push us the stack 
    pushl %eax 
    movl $fault_handler, %eax 
    call *%eax  # A special call, preserves the 'eip' register 
    popl %eax 
    popl %gs # I discovered that the error occures on this line 
    popl %fs 
    popl %es 
    popl %ds 
    popa 
    addl $8,%esp # Cleans up the pushed error code and pushed ISR number 
    iret   # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP! 

.extern irq_handler 
irq_common_stub: 
    pusha 
    push %ds 
    push %es 
    push %fs 
    push %gs 
    movw $0x10,%ax 
    movw %ax,%ds 
    movw %ax,%es 
    movw %ax,%fs 
    movw %ax,%gs 
    movl %esp,%eax 
    pushl %eax 
    movl $irq_handler, %eax 
    call *%eax 
    popl %eax 
    popl %gs # I discovered that the error occures on this line 
    popl %fs 
    popl %es 
    popl %ds 
    popa 
    addl $8,%esp 
    iret 

私は奇妙な何かを見つけました。 QEMUを使用してオペレーティングシステムを.isoのディスクイメージとして実行すると、動作しません。しかし、私がカーネルとして-kernelオプションを指定して呼び出すと、期待通りに機能しました。私はこれに上記のコードを変更し

popl %gs # I discovered that the error occures on this line 
    popl %fs 
    popl %es 
    popl %ds 

:私は以下のコードを変更することを決めた

pop %gs 
    pop %fs 
    pop %es 
    pop %ds 

私はまだGPFを取得しています。私は何か間違っているのですか?助言がありますか?

+2

奇妙なことに、 'push'をしているのですが、' popl' ...一般的に同じ 'push' /' pop'や 'pushl' /' popl'を使うべきです – Buddy

+2

'gs'は正しく初期化されていますか? ?リアルモードから残った値が残っている場合は、それをポップするとGPFが発生します。 PS:デバッガPS#2を使うことを学ぶ: '特別な呼び出し、 'eip'レジスタ' LOLを保持する? – Jester

答えて

3

私の古いメモリが正しく機能する場合、セグメントレジスタは16ビットで、poplを実行しようとしていますが、これは32ビット値をポップします...したがって、問題です。

あなたは上記のpush %gsをやっているので、あなたもpop %gsを行う必要があります。他のレジスタと同じ、あなたpushそれらと同じように必ずpopそれらを作ります。

3
addl $8,%esp # Cleans up the pushed error code and pushed ISR number 

あなたisr_common_stubルーチンは、エラーコードが常にあるだろうと思います。いくつかのフォールトはエラーコードをプッシュしません!割込み番号10,11,12,13,14、および17に関連する障害のみがエラーコードを使用します。

http://www.brokenthorn.com/Resources/OSDev15.htmlから我々が学ぶ:

をハンドラは下の特権レベル(ビット記述子の42-45)で実行されようとしている場合は、スタックスイッチが発生します。ハンドラによって使用される
セグメント・セレクタとスタックのスタックポインタは、現在実行中のタスクのTSSからabtainedれます。プロセッサは、この新しいスタックに割り込みハンドラのスタックセグメントセレクタとスタックポインタをプッシュします。プロセッサは、EFLAGS、CS、およびEIPの現在の状態を新しいスタックに保存します。
例外がを保存するエラーコードが発生した場合、エラーコードは、EIPの後に新しいスタックにプッシュされます。

また

ハンドラは、同じ特権レベルで実行されようとしている場合(現在の特権レベル(CPL)が記述の(ビット42〜45と同じである)
プロセッサ現在のスタックにEFLAGS、CS、EIPの現在の状態を保存します。
例外がを保存するエラーコードが発生した場合は、エラーコードがEIP

後に現在のスタックにプッシュされます0

私たちの割り込みハンドラが呼び出されたときにスタックが押されたかを知ることは非常に重要であり、どのような例外もエラーコードを押してください。

関連する問題