delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/04/26/02:21:54

Date: Sat, 26 Apr 1997 02:17:28 -0400
Message-Id: <199704260617.CAA09891@delorie.com>
Newsgroups: comp.os.msdos.djgpp
Subject: Reeealy stumped with timer handler!
From: cgouldie AT pop3 DOT wt DOT net
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

NNTP-Posting-Host: 206.139.152.228
Message-ID: <33616746 DOT 0 AT news1 DOT wt DOT net>
Date: 26 Apr 97 02:24:06 GMT
Lines: 138
Path: news2.mv.net!mv!news.sprintlink.net!news-fw-22.sprintlink.net!www.nntp.primenet.com!nntp.primenet.com!ix.netcom.com!news-peer.sprintlink.net!news.sprintlink.net!sprint!cpk-news-hub1.bbnplanet.com!news.bbnplanet.com!uunet!in1.uu.net!205.230.159.11!news1.wt.net!206.139.152.228




  I want to sync the timer interrupt with the vertical retrace, to avoid the
overhead of waiting for the retrace every time I want to blit the screen.

  My solution is to make the timer interrupt just before each retrace, then I
will wait for the retrace, then if the screen is ready to blit, I will write
it out. However, I haven't gotten that far yet, because I have run into a big
snag.

  The problem is that if I were to just blit out the screen during the timer
interrupt, this would throw off the timing, and I would end up waiting for
a retrace anyway! So I thought I could instead alter the stack so that it
would return to my own procedure, instead of the point of interruption. This
way, during my blit procedure, the timer could keep going. I could then just
pop the original flags at the end of my blit procedure, and everything should
work fine, right?

  Well, easier said than done. I found that I had to call
dpmi_allocate_iret_wrapper () to wrap around my interrupt handler, or the
interrupt wouldn't happen at the correct frequency. Thus, altering the stack
became a much bigger chore. I had to look at the iret wrapper function to
find out the status of the stack before my procedure is called. I don't know
what in the heck the wrapper is doing, but one thing it seems to do is change
the stack selector and address, and push the old stack selector and address,
respectively, just before calling my procedure. 

  My handler works just fine if I don't mess with the stack.

  Without further ado, here is the wrapper function (from fsdb), and my
handler. I have it set up to increment a tick counter. When the tick counter
reaches 2000 ticks, the wrapper function (theoretically) returns to the
function test_alt_ret, which (theoretically) returns to the point of
interruption.

;Written down by hand from fsdb. Reproduced exactly, minus the addresses,
;plus the function name and the label (downthere). Obviously I couldn't
;comment it much, as I did not write it.

wrapper_func    proc near
                push    ds
                push    es
                push    fs
                push    gs
                pusha              ;48 bytes pushed onto stack? Assumed.
                mov     ax,247                            
                mov     ds,ax
                inc     [0x68008]  ;I wonder what these addresses are?
                cmp     [0x68004],0
                jnz     downthere
                mov     [0x68004],1
                mov     es,ax
                mov     fs,ax
                mov     gs,ax
                mov     ebx,6fe00
                cld
                mov     ecx,esp
                mov     dx,ss
                mov     ss,ax            ;new stack address
                mov     esp,ebx
                push    edx               ;pushing old stack address
                push    ecx
                call    _timerhandler    ;now it calls my function
                pop     eax
                pop     ebx
                mov     ss,bx
                mov     esp,eax
                mov     [0x68004],0
downthere:      popa
                nop
                pop     gs
                pop     fs
                pop     es
                pop     ds
                iret
wrapper_func    endp


.386
.model flat
.code

extrn c ticks
public c timerhandler

;after 2000 ticks, the wrapper should return here.

test_alt_ret    proc    near
                popfd
                ret
test_alt_ret    endp

;Here's my timer handler. I assumed (since I couldn't really tell from any
;documentation) that 8 bytes are pushed onto the stack before entry into
;the wrapper function (flags, cs, ip). I believe that I also tried it as 12
;bytes.

timerhandler    proc    near
                pushad
                cli
                inc     ticks
                cmp     ticks, 2000
;If I change jne to jmp, this procedure works just fine. Else: exit code 0xff.
                jne     nottime
                mov     eax, [esp+4]  ;this should be the old stack address
                mov     ebx, [esp+8]  ;should be old stack selector
                mov     ebp, esp      ;save current stack selector & address
                mov     dx, ss
                mov     ss, bx    ;change selector and address to old value
                mov     esp, eax
                mov     esi, esp
         ;Next 5 lines add 8 bytes to stack for old return address & flags
                sub     esp, 8
                mov     edi, esp
                mov     ecx, 64
                cld
                rep     movsd
                mov     ebx, [esp+48] ;save return address
                mov     [esp+56], ebx
                xor     ebx,ebx
                mov     bx, [esp+54]      ;save old flags
                mov     [esp+60], ebx
                lea     ecx, test_alt_ret ;make wrapper return to my func
                mov     [esp+48], ecx
                mov     ss,dx           ;restore stack
                mov     esp,ebp
nottime:        mov     al, 20h        ;acknowledge interrupt
                out     20h, al
                sti
                popad
                ret
timerhandler    endp

end


Net-Tamer V 1.08 - Test Drive

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019