News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Timer Tick

Started by Dinosaur, August 04, 2005, 12:05:37 PM

Previous topic - Next topic

Dinosaur

Hi all

I have implemented a hook onto the Timer Tick interupt, and created code that would update a varaible in Basic with that count.
This precvents me from calling for updates and I always have the latest count.

Currently investigating converting to FreeBasic, which runs in protected mode, which is basically chinese to me.
It has in-line asm which together with other features is a great attraction.

I am using Timer Tick as an example, but have implemented other interupt hooks as well which have the same conversion need.
The code I produce runs on industrial machines in a pure dos environment using the Win95 dpmi.
The dos interface in FreeBasic is based on the DJGPP library.

Have googled extensively and spend countless hours reading and getting more confused.

My problem is that I cant seem to confirm if there is a protected mode Timer Tick available that I can hook onto,(and how)
without causing a switch to real mode when my variable is updated.
It also appears that a switch to real mode occurrs to handle some of these interupts.

Most of the info available assumes dos applications running in a dos window with whatever Win version resources available.
Similarly it assumes the complexity required for multiple task applications.

My application is one where I own the machine, and nothing else will ever run at the same time as my application.
The other int I have hooked are:
Keyboard (stop polling all day for possible key stroke)
TouchScreen , same reason
Hardwired int that updates an adc count 2000 times per second.

Can somebody steer me in the right direction.

Regards

P1

Are you then using the DOS7 of Win95 as a boot environment to host your program in?

If so, this is a 16 bit DOS question.  And standard DOS programming techniques apply.  You do want to use interupt hooks still, right?

If your using a Complied Basic program in a DOS OS, then I recommend Power Basic for DOS.  It has very good support for ASM subroutines. 

http://www.powerbasic.com/products/pbdos/

If your looking to go to outside of DOS, please consider that you will force your users to upgrade their hardware to accomodate your re-written software.

Regards,  P1  :8)

Gustav


> My problem is that I cant seem to confirm if there is a protected mode Timer Tick

Of course there is one. And what's better, you don't need to care about real-mode hooking in dpmi, because the IRQ is reflected to protected mode by the dpmi host. So just hook interrupt in protected mode (using dpmi int 31h, ax=0204h/0205h).

Dinosaur

P1

I thought very carefully about the section I was  posting in.
16 bit dos, it was not.

Anyhow, yes using dos7, but FreeBasic is 32bit and will not run in real mode.
Actually bought Powerbasic a while ago, but there are too many differences that would require re-writing.

Gustav, I actually got that detail, but had doubts that all the info for that int were there.
Will try again.

Regards

Dinosaur

Hi all

I do think I need help here.
Below the code from 16bit app.

.MODEL  MEDIUM
.486
.CODE
;-------------------------
PUBLIC    TSRTIME
OldHandle     DD   ?
VarblSeg       DW  ?
VarblOfs        DW  ?
;-------------------------

TSRTIME    PROC    FAR
;------------
PUSH    BP
MOV     BP,SP
;------------
push    ds                                                  ;for return to basic
push    cs
pop     ds                                                  ;set to current CS
;------------
MOV    BX,[BP+6]                                       ;segment of basic variable
CMP     BX,0                                               ;if zero then program is terminating
JZ        Restore                                          ;so restore old handler.
MOV    VarblSeg,BX
MOV    BX,[BP+10]                                     ;offset of basic variable       
MOV    VarblOfs,BX
;-----------------------------------
cli                                                             ;no int whilst re-assigning int.
mov     ax, 351Ch ;get function 35
int       21h                                                ;get vector for timer tick
mov     WORD PTR OldHandler[0], bx            ;save addr of original handler
mov     WORD PTR OldHandler[2], es
mov     ax, 251Ch                                       ;function 25h
mov     dx, OFFSET TsrTimer                        ;new handler addr
int       21h                                                 ;set vector with addr of new handler
sti
;----------------------------------
jmp     Dos_Exit
Restore:
               cli                                                              ;no int whilst re-assigning int.
               lds      dx,OldHandler
               mov    ax,251Ch
               int       21h
               sti
               jmp     Dos_Exit


TsrTimer PROC   FAR
;---------
PUSH    DS
PUSH    BX
;---------------
                mov     ds,VarblSeg                      ;set seg to Basic's variable
                mov     bx,VarblOfs                      ;set ofs "   "         "
                inc      dword ptr [bx]                  ;inc the timer tick
;---------------
POP     BX
POP     DS
;*********
jmp      cs:OldHandler
TsrTimer ENDP
;---------------------------------------
Dos_Exit:
pop ds ;restore basic's DS
POP BP ;
ret 8 ;clean up
TSRTIME ENDP
END


Now I tried to convert it to protected mode.
This is in-line asm for FreeBasic.

SUB HookInt
asm
    xor     eax,eax
    mov     TickCount,eax
    '--------------------
    mov     ax,&H0204
    mov     bx,&H1c
    int       &h31
    mov     OldHandler,edx
    '--------------------
    mov     ax,&H0205
    mov     bx,&H1c
    lds       edx,SaveTick
    int       &H31
    jnc      HookExit
    mov    TickCount,eax
    jmp     HookExit
    '--------------------
SaveTick:
    mov    eax,TickCount
    inc      eax
    mov    TickCount,eax   
    iret
HookExit:
end asm
END SUB


Of course it doesnt work. (otherwise I wouldnt ask the question)
Do I need to issue an IRET, or do I need to return to the original handler, and how ?

Regards


PS. I hate the way it cant handle tabs in code on this site.

Gustav


this looks a bit better


    mov     dssave,ds              ;you will need a value for ds in the timer interrupt. Must be accessible with CS
    mov     ax,&H0204
    mov     bx,&H1c
    int       &h31
    mov     OldHandler+0,edx
    mov     OldHandler+4,cx       ;you will get int vector in CX:EDX!
    '--------------------
    mov     ax,&H0205
    mov     bx,&H1c
;    lds       edx,SaveTick            ;dont use ds:edx, use CX:EDX!
    mov    cx,cs
    mov    edx, offset SaveTick
    int       &H31
    jnc      HookExit
    xor      eax, eax
    mov    TickCount,eax
    jmp     HookExit
    '--------------------
SaveTick:
    push   eax                           ;save all registers which are modified!
    push   ds
    mov    ds, cs:[dssave]
    mov    eax,TickCount
    inc      eax
    mov    TickCount,eax 
    pop    ds
    pop    eax
    iretD                                   ;use IRETD


Dinosaur

Gustav

Many thanks for that.
That works just great, but now I have to experiment and understand why it works.

Regards

P1

Dinosaur,

I wonder just how Gustav's solution is not 16 bit code?  And why it should go outside of this forum?

My goal was to help you get an acceptable solution.  But we have not address the FreeBasic problem yet.  But that was not the problem at hand.

Regards,  P1  :8)

Dinosaur

P1

Your intention was appreciated, all I wanted was a solution, and I got it. :U
I guess if FreeBasic runs in protected mode, my interpretation was that it was not a 16 bit problem.
Gustav's solution may be, but in my mind it was a 32 bit problem.(blame my mother)

But hey, problem solved, thanks to you guys.

Regards


Dinosaur

Hi all

Have converted my int hook routine for the keyboard, but although my flag is being incremented, there are
no keys (in basic). In the 16 bit version it worked nicely.
Is this hook expecting me to read the key during the int.?
Is the key being thrown away by the original handler.?

SUB HookKbdInt
asm
    mov     Kbdds,ds                    'get a copy of current ds             
    mov     ax,&H0204                   'get addr of current handler
    mov     bx,&H09                     'for KeyBrd
    int     &h31                        'call ptotected mode int.
    mov     OldKbdInt+0,edx             'and save addr as OldKbdInt
    mov     OldKbdInt+4,cx       
    '--------------------
    mov     ax,&H0205                   'assign an extra handler
    mov     bx,&H09                     'for the Kbd
    mov     cx,cs
    mov     edx, offset SetKbdFlag      'offset of label where we
    int     &H31                        'want the int to go
    jnc     KbdExit                     'if no error jump to exit
    mov     KbdFlag,eax                 'otherwise use it as err store.
    jmp     KbdExit                     'get out by jumping over int routine.
    '--------------------
SetKbdFlag:
    push   eax                          'save all registers which are modified!
    push   ds
    xor    eax,eax
    mov    ds, cs:[Kbdds]               'set it to segment of our variable.
    mov    ax,KbdFlag
    inc    ax                           'increment keyboard flag
    mov    KbdFlag,ax
    pop    ds                           'restore ds of other handler.
    pop    eax                          'restore registers
    iretD                               'and return to old handler.
KbdExit:   
end asm
END SUB



When I press a key, the KbdFlag increments to 1.
Then using a basic statement
K$ = Inkey$

K$ is blank.
What am I doing wrong ?

Also I have written UnHook code.

SUB UnHookTickInt
asm
    '----------
    push    eax
    push    ebx
    push    ecx
    push    edx
    '----------
    mov     ax,&H0205                   'assign new handler
    mov     bx,&H1c                     'for Timer Tick.
    mov     edx,OldTickInt+0            'restore addr
    mov     cx,OldTickInt+4       
    int     &H31                       
    jnc     UnTickExit                  'if no error jump to exit
    mov     TickCount,eax               'otherwise use it as err store.
UnTickExit:   
    pop     edx
    pop     ecx
    pop     ebx
    pop     eax
end asm
END SUB


It works correctly, but there is a gnawing feeling that I am simply hooking the old interupt onto the old interupt. ?
Also, if I have incorrectly intrepeted gustav's code with the comments, I would love it to be corrected.

Regards

Gustav


> Is this hook expecting me to read the key during the int.?

Yes. Unlike int 1Ch, which is a software interrupt, int 9 is a hardware interrupt routine.

So either you must handle the keyboard (and PIC) - or just jmp to the old handler:


    push   eax                          'save all registers which are modified!
    push   ds
    xor    eax,eax
    mov    ds, cs:[Kbdds]               'set it to segment of our variable.
    mov    ax,KbdFlag
    inc    ax                           'increment keyboard flag
    mov    KbdFlag,ax
    pop    ds
    pop    eax                          'restore registers
    jmp fword ptr cs:[OldKbdInt]




Dinosaur

Hi all

Just an update
For some reason FreeBasic would only work with

    ljmp   cs:[OldKbdInt]


which appears like AT&T syntax.

Anyhow thanks for all your help.
Regards