ASM - timer hook - local variable?

Started by
13 comments, last by izzo 19 years, 6 months ago
I'm using TASM (16bit .exe) for this. I'm trying to integrate the 18.2 timer into my assembly code and it is exhibiting some weird behavior. Basically what I'm doing is this, I have a main procedure that sets up the timer, which I'm sure is being called. I have the following globals:
X               dw   11
timerIntSeg     dw   1
timerIntOffset  dw   1

The timer set up code:
    push ds
    push cs
    pop ds
    ;Get the user defined timer interupt vector
    mov ax, 351Ch
    int 21h
    mov timerIntSeg, es
    mov timerIntOffset, bx
    
    ;Set it to the demo timer
    mov ah, 25h
    mov dx, OFFSET timerInt
    int 21h
    pop ds

Again, the timer is being called. The main procedure code:
    mov bx,X

    mov ah,6
    mov dl,bl
    int 21h

    xor ax,ax 	; function 00h - get a key
    int 16h 	; call BIOS service

    mov bx,X

    mov ah,6
    mov dl,bl
    int 21h

    xor ax,ax 	; function 00h - get a key
    int 16h 	; call BIOS service

And the end of the main procedure where the timer is reset/called:
END_PROGRAM:
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;      Reset the timer interrupt          ;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    mov ax, 251Ch
    mov dx, timerIntOffset
    mov bx, timerIntSeg
    mov ds, bx
    int 21h

    mov ax,4C00h 		; exit to DOS
    int 21h

    ;Here is where we redraw and check if escape has been pressed
timerInt:
   
    mov bx,X

    mov ah,6
    mov dl,bl
    int 21h
    inc X
endTimer:
    iret

    main endp

As you can see, the program should do the following: print X (11, or the male sign) - this works wait for keypress print X wait for keypress exit Those steps work. However, during this, the timer should print out x (which it sort of does), and then increment x. What is really happening: X prints as character 11 The timer prints the characters, starting from 0 (null) and incrementing, then at keypress character 11 is printed again, then the timer prints out continuing from the last character it printed. Textually: 11 0 1 2 3 4 5 6 (keypress)11 7 8 9 10 11 12 (keypress)(exit) Any ideas on this? Is x treated as a local variable or something like that? [Edited by - kordova on September 29, 2004 9:53:01 PM]
Advertisement
In an Interrupt handler, you should do the least work possible. You shouldn't call another Int before Iret.

Thermo
That was just to make sure it was working. Anyway, with or without the print interrupt, it's not incrementing X.
dunno... perhaps you should write [x] instead of x... not sure though

Thermo
Quote:Original post by Konfusius
dunno... perhaps you should write [x] instead of x... not sure though

Thermo

[X] comes out the same as X. I'm using TASM.
What assembler are you using? Different assemblers use different ways of accessing variables; some require you to use [X], some will work with just X.

It looks okay to me.. 'X' is not a local variable (that sort of concept doesn't really exist in an assembler). Is everything in the same segment? Is this a .COM file?

cheers
sam
Quote:Original post by izzo
What assembler are you using? Different assemblers use different ways of accessing variables; some require you to use [X], some will work with just X.

It looks okay to me.. 'X' is not a local variable (that sort of concept doesn't really exist in an assembler). Is everything in the same segment? Is this a .COM file?

cheers
sam

It's Tasm, and by default (as far as I can tell) it's generating .exe's. (And it's 16bit in case that wasn't obvious)
Quote:Original post by izzo
What assembler are you using? Different assemblers use different ways of accessing variables; some require you to use [X], some will work with just X.

It looks okay to me.. 'X' is not a local variable (that sort of concept doesn't really exist in an assembler). Is everything in the same segment? Is this a .COM file?

It's an .exe, and I'm rather new to this.

I have a .data where the above data is defined and then a .code like this:
.codemain proc    mov ax,@data 	; set up DS to point to data segment    mov ds,ax 		; use axPROGRAM_ENTRY:    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;    ;;         Init/Set User Timer             ;;    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;    push ds    push cs    pop ds    ;Get the user defined timer interupt vector    mov ax, 351Ch    int 21h    mov timerIntSeg, es    mov timerIntOffset, bx        ;Set it to the demo timer    mov ah, 25h    mov dx, OFFSET timerInt    int 21h    pop dsPROGRAM_LOGIC_ENTRY:    mov bx,[X]    mov ah,6    mov dl,bl    int 21h    xor ax,ax 	; function 00h - get a key    int 16h 	; call BIOS service    mov bx,X    mov ah,6    mov dl,bl    int 21h    xor ax,ax 	; function 00h - get a key    int 16h 	; call BIOS serviceEND_PROGRAM:    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;    ;;      Reset the timer interrupt          ;;    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;    mov ax, 251Ch    mov dx, timerIntOffset    mov bx, timerIntSeg    mov ds, bx    int 21h    mov ax,4C00h 		; exit to DOS    int 21htimerInt:        mov bx,[X]    mov ah,6    mov dl,bl    int 21h    ;inc [X]    inc XendTimer:    iret    main endpend main
I can't figure it out exactly, but I can only guess that you are messing up your DS at some point (Because of that 11, 0, 1, 2, 3, 4, 5, 6, 11, 7, 8... behaviour, really looks like you are writing somewhere to foreign unused memory).

What I wonder is why you do this:

push ds
push cs
pop ds

....

pop ds.

The first pop is supposedly giving you access to your data, like in a COM program (I know my english is bad), nothing wrong, but the second pop restores it to its previous value, which might not be what you want.
Sorry, I am too sleepy now to be of better help (as if I ever could be :) )

KonfuThermo
You're right. Putting:
mov ax,@data ; set up DS to point to data segment
mov ds,ax ; use ax

At the head of the interrupt does it.

Is this a solution or what is wrong that I could correct?

This topic is closed to new replies.

Advertisement