I'm writing an interrupt service routine which is supposed to process interrupts caused by RTC using int 70h and IRQ8 for use with some timer. Unfortunately, I've been having lots of problems with that, so I decided to separate the issue into several smaller problems and then solve each one independently. For start, I gave up on the hardware part and decided to first implement interrupt in software.
Right now, I'm using NASM and DosBox.
Here's the ISR code:
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
I'm testing this interrupt using following programs:
;myint
org 100h;installs the interrupt
segment .code
main:
call _inst_70
;call _uninst_70 ; THIS IS ON PURPOSE!
ret
%include "myint.asm"
and
;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
Now we're getting to the interesting part.
When I call the installation program, I get the message that the interrupt is installed and the program seems to end fine.
When I call INT70H.COM, I get what seems to be a dump of an area of memory. The only readable things in that are:
Testing!Testing!int 70h working
and C:\NASM-DOS\NASM.EXE
.
When I uncomment the mov ax, 0
and mov dx, 0
lines in INT70H, I get Testing!
and DosBox hangs and sometimes crashes. Same happens of VMware and VirtualBox.
When I comment out the lines which are reading register C of the RTC with the two movs from INT70H commented, I get Testing!Testing!int 70h working
and DosBox hangs. Same thing happens on VirtualBox and VMware. If the two movs in INT70H are uncommented, I get Testing!
and hang.
This lead me to believe that it could be some DOS system calls (which I'm not supposed to use in the end product) could be doing something bad, but even with them commented out, when I run INT70H, computer hangs.
My main problem is that right now I have absolutely no idea how to start working on this problem.
This was a really strange bug. Thanks a lot to all who helped, but in the end, it turned out that when I was setting up the RTC, I didn't set output register to B before writing to it. Now it works fine.