2011-12-27 15 views
3

私はいくつかのタイマで使用するためにint 70hとIRQ8を使ってRTCによって引き起こされた割り込みを処理すると思われる割り込みサービスルーチンを書いています。残念ながら、私はそれに多くの問題を抱えてきたので、問題をいくつかの小さな問題に分けて、それぞれを個別に解決することに決めました。まず、ハードウェアの部分をあきらめて、最初にソフトウェアで割り込みを実装することに決めました。割り込みサービスルーチンからの奇妙な動作

今はNASMとDosBoxを使用しています。

ここISRコードがあります:

segment .code 
; ---------------------------------------------- 
; writes a message on the screen 
; every time interrupt is called 
; ---------------------------------------------- 

INT_CODE equ 070h 

my_int: 
    pusha   ;saves all registers on stack so they get preserved 

    ;EDIT1 
    xor ax, ax  ;sets ax to zero 
    mov es, ax  ;puts zero into extra segment register 
    mov bx, [es:INT_CODE*4+2] ;this should give us the sergment of the ISR 
    mov ds, bx  ;the segment is now in ds 
    ;END OF EDIT1 

    ;mov ax, 0  ;cleans any garbage in ax 

    ;mov ah, 09h ;preparing to call DOS system call, remove later 
    mov ax, string_s 
    mov si, ax 
    call _print_string 


    ;int 021h  ;this should hopefully work 

    mov al, 0Ch  ; Accessing RTC 
    out 070h, al ; register C should be read 
    in al, 071h  ;or there won't be any new interrupts (or so it's supposed to be) 

    ;mov ax, 0  ; again we clear anything left in ax, just in case 
    ;mov ah, 09h ; preparing to write string 
    mov ax, string_e 
    mov si, ax 
    call _print_string 
    ;int 021h  ; this should work 

    mov al, 20h  ;we're letting PICs know the interrupt ended 
    out 0A0h, al ;notifying second PIC 
    out 020h, al ;notifying first PIC 

    popa   ;application gets its registers back 

    iret 

_inst_70: 
    cli    ;hardware interrupts are now stopped 
    xor  ax, ax 
    mov  es, ax 
    mov  bx, [es:INT_CODE*4] 
    mov  [old_int70_off], bx 
    mov  bx, [es:INT_CODE*4+2] 
    mov  [old_int70_seg], bx 

; adding our routine to interrupt vector table 
    mov  dx, my_int 
    mov  [es:INT_CODE*4], dx 
    mov  ax, cs 
    mov  [es:INT_CODE*4+2], ax 
    sti 

    ;mov ah, 09h 

    mov ax, string_inst 
    mov si, ax 
    call _print_string 
    ;int 021h 

    ret 

; ----------------------------------------------------------------------------- 
; return old int 70 h 

_uninst_70: 
    cli 
    xor  ax, ax 
    mov  es, ax 
    mov  ax, [old_int70_seg] 
    mov  [es:INT_CODE*4+2], ax 
    mov  dx, [old_int70_off] 
    mov  [es:INT_CODE*4], dx 
    sti 
    ret 

_print_string: 

    pusha 
    mov  ah, 0Eh      ; BIOS INT 10h teletype (TTY) function 
.Repeat: 
    lodsb        ; takes one character from a string 
    cmp  al, 0 
    je  .End       ; If it's zero, end of string 
    int  10h       ; if not, call BIOS 
    jmp .Repeat      ; and go to next character 
.End: 
    popa 
    ret 

segment .data 

string_s: db 'We're in ISR',0 
string_e: db 'It's working',0 
string_inst: db 'Installed',0 

old_int70_seg: dw 0 
old_int70_off: dw 0 

私は以下のプログラムを使用した割り込み、これをテストしている:

;myint 
org 100h;installs the interrupt 
segment .code 

main: 
    call _inst_70 

    ;call _uninst_70 ; THIS IS ON PURPOSE! 
    ret 

%include "myint.asm" 

;int70h 
org 100h   ;calls the interrupt 
segment .code 
    mov ah, 09h  ; getting ready to print string 
    mov dx, string1 
    int 21h 

    ;mov ax, 0  ;getting rid of the last message 
    ;mov dx, 0 

    int 070h  ;calling the interrupt 

    mov ah, 09h 
    mov dx, string2; 
    int 21h 

    ret 

segment .data 
string1: db 'Testing!',0 
string2: db 'int 70h working',0 
_print_string: 

     pusha 
     mov  ah, 0Eh   ; BIOS INT 10h teletype (TTY) function 
.Repeat: 
     lodsb     ; takes one character from a string 
     cmp  al, 0 
     je  .End    ; If it's zero, end of string 
     int  10h    ; if not, call BIOS 
     jmp .Repeat   ; and go to next character 
.End: 
     popa 
     ret 

今、私たちは面白いに取得しています部。

インストールプログラムを呼び出すと、割り込みがインストールされているというメッセージが表示され、プログラムがうまく終了しているようです。

INT70H.COMを呼び出すと、メモリ領域のダンプのように見えます。読み取り可能なものは、 Testing!Testing!int 70h workingC:\NASM-DOS\NASM.EXEです。

私はINT70Hでmov ax, 0mov dx, 0行のコメントを解除すると、私はTesting!とDOSBoxをハングアップを取得し、時々クラッシュします。 VMwareとVirtualBoxの場合も同じです。

INT70Hからの2つのムーブでRTCのレジスタCを読み込んでいる行をコメントアウトすると、Testing!Testing!int 70h workingとなり、DosBoxがハングアップします。 VirtualBoxとVMwareで同じことが起こります。 INT70Hの2つのムーブメントにコメントがない場合は、Testing!とハングアップします。

これは、DOSシステムコール(私は最終製品で使用するはずがない)が悪いことをするかもしれないと信じていますが、INT70Hを実行するとコメントアウトしてもコンピュータハングアップします。

私の主な問題は、今、私はこの問題に取り組む方法を全く考えていないということです。

+2

完全な回答はありませんが、あなたのプログラムは[TSR](http://en.wikipedia.org/wiki/Terminate_and_Stay_Resident)にする必要があります。 – interjay

+0

@interjayそれは私がプログラムを書いていることを暗示しています。これは後でオペレーティングシステムスケジューラの一部となり、PITを使用せずに100ミリ秒のタイムベースを取得しようとしています。だから私は最終結果のDOS機能に依存することはできません。 :) – AndrejaKo

+0

ハードウェア割り込みハンドラでDOS割り込みを使用することはできませんが、再入可能ではありません。 –

答えて

0

これは本当に奇妙なバグでした。助けてくれたすべての人に感謝していますが、結局、RTCを設定していたときに、出力レジスタを書き込む前に出力レジスタをBに設定しなかったことが判明しました。今それは正常に動作します。

1

割り込みサービスルーチンは、セグメントレジスタを設定する必要があります。割り込みが呼び出されると、システム内には絶対に何かのコンテキストが存在する可能性があります。印刷文字列の呼び出しは、文字列アドレスにds:dxを使用しているため、特に問題がありますが、dsは設定されていません。

それ以外は、外見上は上手く見えます。 dsを設定するとハングの問題が解決するかどうかを確認してください。もしそうでなければフォローアップしてください。

+0

大きな改善点は、INT70Hの 'mov ax、0'がコメントアウトされ、サービスルーチンの最初の' mov ax、0'がメモリの内容を出力してハングすることです。以前はそれをしていませんでした。 – AndrejaKo

1

割り込みサービスルーチン(ISR)は、使用中のレジスタをすべて保存して復元する必要があります(中断されたソフトウェアにはランダムにゴミ箱が表示されないようにする必要があります)。これには、セグメントレジスタ(DSやESなど)が含まれます。 "push ds"と "push es"がISRの先頭近くにあり、対応する "ポップ"指示が "iret"の前に必要です。

いずれのBIOS機能もリエントラントではないため、ISRでこれらのBIOS機能を使用することは危険です。実行中の可能性のある他のコードが使用されていないことを保証できる場合を除きます。これには、 "int 0x10、ah = 0x0E"関数(メインコードで使用しているISRとメインコードを中断する)が含まれます。それがテストのためだけにあれば。代わりにディスプレイメモリに直接書き込みを試みてください(たとえば、テキストモードの場合は "mov ax,0xB800; mov es,ax; inc word [es:0]")。

OSコードをテストする場合は、OSコードをテストする方が簡単です。たとえば、これが意図的に返されなかったブートセクタで実装されていた(ロックされている)場合。以前のIVTエントリの保存/復元を気にする必要はなく、DOSやTSRがバックグラウンドで何をしているかを心配してテストを妨げることもありません。 BochsのようなものでDOS/FreeDOSを仮想マシンの中に最初にインストールしなくても、それをデバッグすることができます。追加のボーナスとして、16ビットのリアルモードコードを後で書き換えるのではなく、ターゲットの動作モード(たとえば、32ビット保護モードなど)で実行することができます。

関連する問題