일부 타이머와 함께 사용하기 위해 int 70h와 IRQ8을 사용하는 RTC로 인한 인터럽트를 처리해야하는 인터럽트 서비스 루틴을 작성하고 있습니다. 불행하게도, 나는 많은 문제를 겪어 왔기 때문에 문제를 몇 가지 작은 문제로 분리하고 각각을 독립적으로 해결하기로 결정했습니다. 처음에는 하드웨어 부분을 포기하고 먼저 소프트웨어에서 인터럽트를 구현하기로 결정했습니다.인터럽트 서비스 루틴의 이상한 동작
지금 당장 NASM과 DosBox를 사용하고 있습니다.
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
이제 우리는 흥미를 얻고을 여기
는 ISR 코드입니다 부품.설치 프로그램을 호출하면 인터럽트가 설치되었다는 메시지가 나타나고 프로그램이 정상적으로 종료 된 것처럼 보입니다.
INT70H.COM을 호출하면 메모리 영역을 덤프하는 것으로 나타납니다. 읽을 수있는 유일한 것들은 Testing!Testing!int 70h working
및 C:\NASM-DOS\NASM.EXE
입니다.
INT70H에서 mov ax, 0
및 mov dx, 0
행의 주석을 제거하면 Testing!
이 표시되고 DosBox가 중단되고 때때로 충돌합니다. VMware와 VirtualBox도 마찬가지입니다.
내가 INT70H에서 두 개의 movs와 RTC의 레지스터 C를 읽고있는 줄을 주석으로 처리하면 Testing!Testing!int 70h working
이되고 DosBox가 중단됩니다. 버추얼 박스와 VMware에서도 똑같은 일이 일어납니다. INT70H에서 두 개의 mov 파일의 주석 처리가 해제 된 경우 Testing!
이 표시되고 멈 춥니 다.
이것은 일부 DOS 시스템 호출 (최종 제품에서 사용하지 않아야 함)이 나쁘다고 생각할 수도 있지만 INT70H를 실행할 때 주석 처리 된 경우에도 컴퓨터 멈 춥니 다.
내 주요 문제는 바로 지금이 문제에 대한 작업을 시작하는 방법을 전혀 모른다는 것입니다.
전체 답변을 드릴 시간이 없지만 프로그램을 [TSR] (http://en.wikipedia.org/wiki/Terminate_and_Stay_Resident)으로 만들어야합니다. – interjay
@interjay 그건 내가 프로그램을 쓰고 있음을 암시합니다. 나중에 운영 체제 스케줄러의 일부가 될 것이며 PIT를 사용하지 않고 100ms 타임베이스를 얻으려고합니다. 그래서 최종 결과에 DOS 기능을 의지 할 수는 없습니다. :) – AndrejaKo
하드웨어 인터럽트 처리기에서 DOS 인터럽트를 사용할 수 없으며 재진입이 불가능합니다. –