Hello,
I'm playing with a dos extended application which uses the RTC timer at IRQ 8.
This is the test app, which displays a counter at the upper right corner of the screen. The timer usually has a frequency of 1024 Hz.
a side note: the code runs in a true-flat 32bit memory model!
;*** test irq 8 ***
.386
.Model FLAT, stdcall
.data
oldint70 df 0
csalias dw 0
dwScrnPos dd 0
bMask db 0
bStatus db 0
.code
; increment the screen counter
IncScr proc uses ecx ebx
mov cl,8
mov ebx,cs:[dwScrnPos]
nextchar:
inc byte ptr [ebx]
cmp byte ptr [ebx],'9'
jbe done
mov byte ptr [ebx],'0'
dec ebx
dec ebx
dec cl
jnz nextchar
done:
ret
IncScr endp
; irq 8 handler
myint70 proc
push ds
mov ds,cs:[csalias]
call IncScr
pop ds
db 2eh ;CS prefix
jmp fword ptr oldint70
myint70 endp
; init the screen counter
InitScr proc
mov eax,0B8000h
add eax,79*2
mov dwScrnPos,eax
mov cl,8
nextchar:
mov byte ptr ds:[eax],'0'
dec eax
dec eax
dec cl
jnz nextchar
ret
InitScr endp
main proc c
mov [csalias],ds
call InitScr
mov ax,0204h
mov bl,70h
int 31h
mov dword ptr [oldint70+0],edx
mov word ptr [oldint70+4],cx
mov ax,0205h
push cs
pop ecx
mov edx, offset myint70
int 31h
in al,0A1h
mov bMask, al
and al,not 1 ;unmask IRQ 8
out 0A1h,al
in al,021h ;unmask IRQ 2
and al,not 4
out 021h,al
cli
mov al,0Bh
out 70h,al
in al,71h
mov bStatus, al
or al,40h
out 71h, al
sti
main_0:
mov ah,0
int 16h
cmp ah,1 ;wait until ESC is pressed
jnz main_0
exit:
cli
mov al,0Bh
out 70h,al
mov al,bStatus
out 71h, al
sti
mov al,bMask
out 0A1h,al
mov ax,0205h
mov bl,70h
mov cx, word ptr [oldint70+4]
mov edx, dword ptr [oldint70+0]
int 31h
mov ah,4ch
int 21h
ret
main endp
END main
The problem is that it works only when launched the second - and any further - time. When running the first time the interrupt procedure is called only once, then the counter stops!
Any ideas why?
I don't know that this could cause the problem, but hardware interrupt handlers are generally supposed to preserve all registers, and yours is altering EAX and CL in the call to InitScr.
Hi,
InitScr is not called by the interrupt handler, just IncScr.
Sorry, too many distractions.
I think the problem is that csalias is defined in the data segment and the handler expects to find it in the code segment.
> I think the problem is that csalias is defined in the data segment and the handler expects to find it in the code segment.
the model is flat so using CS as segment prefix for accessing members in .DATA is valid. If this wouldn't work I would get GPFs.
But I found the error in the meantime. As it turned out one has to access the RTC ports (port 71h, index 0Ch) to reenable RTC interrupts. It is quite similiar to the keyboard, where one has to access port 60h to tell the keyboard device that the interrupt was handled.
And then, why did it work when launched the second time? That has to do with how the BIOS works. There is a built in timer software (int 15h, ax=86h), which comes in the way and which does read the RTC status port, but without further action it is sort of "one shot".
Quote
the model is flat so using CS as segment prefix for accessing members in .DATA is valid. If this wouldn't work I would get GPFs.
OK, but why the DS override in InitScr, and the CS override in IncScr?
I am curious how you are building this, and how it is being loaded.
> OK, but why the DS override in InitScr, and the CS override in IncScr?
they are both redundant, I copied some parts of the source from another app.
I use the hx dos extender, which supports PE file format natively.
I attached the binary, source and makefile
[attachment deleted by admin]
Thanks :U