私はいくつかのタイマで使用するために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 working
とC:\NASM-DOS\NASM.EXE
です。
私はINT70Hでmov ax, 0
とmov dx, 0
行のコメントを解除すると、私はTesting!
とDOSBoxをハングアップを取得し、時々クラッシュします。 VMwareとVirtualBoxの場合も同じです。
INT70Hからの2つのムーブでRTCのレジスタCを読み込んでいる行をコメントアウトすると、Testing!Testing!int 70h working
となり、DosBoxがハングアップします。 VirtualBoxとVMwareで同じことが起こります。 INT70Hの2つのムーブメントにコメントがない場合は、Testing!
とハングアップします。
これは、DOSシステムコール(私は最終製品で使用するはずがない)が悪いことをするかもしれないと信じていますが、INT70Hを実行するとコメントアウトしてもコンピュータハングアップします。
私の主な問題は、今、私はこの問題に取り組む方法を全く考えていないということです。
完全な回答はありませんが、あなたのプログラムは[TSR](http://en.wikipedia.org/wiki/Terminate_and_Stay_Resident)にする必要があります。 – interjay
@interjayそれは私がプログラムを書いていることを暗示しています。これは後でオペレーティングシステムスケジューラの一部となり、PITを使用せずに100ミリ秒のタイムベースを取得しようとしています。だから私は最終結果のDOS機能に依存することはできません。 :) – AndrejaKo
ハードウェア割り込みハンドラでDOS割り込みを使用することはできませんが、再入可能ではありません。 –