x86 Assembly

Moderators: None (Apply to moderate this forum)
Number of threads: 4533
Number of posts: 15961

This Forum Only
Post New Thread
Single Post View       Linear View       Threaded View      f

Report
How to make a timer? Posted by i2k_flame on 18 Sept 2003 at 7:26 PM
This is what I came up with by my self, but I am sure there are other ways to make a computer "sleep" for a certain time. I was thinking more in the lines of multi-tasking so that a processor could perform other actions (like tracking a mouse or making calculations) while it's sleeping. Any ideas?

MOV BH,05h ;set sleeping time for 5 seconds
MOV AH,2Ch
INT 21h ;call interupt to record the current time
MOV [DI],DH ;record the number of seconds to memory

label1:
INT 21h ;call interupt again to record the current time
SUB DH,[DI] ;subtract first time form second time
CMP DH,BH ;compare the time passed to the time needed to pass
JB label1 ;jump to the top if 5 seconds didn't pass
Report
Re: How to make a timer? Posted by Bitdog on 18 Sept 2003 at 8:30 PM

In the BIOS memory segment their is a Dword that counts the
seconds since midnight. You can check that for time+wait_time.
0040:006Ch or
0000:046Ch it's the same address.
XOR AX,AX
MOV ES,AX
MOV EAX,[ES:046Ch] ; git the Dword (HI nybble is always 0)
ADD EAX,TIMEtoKILL
Then have the check time in your mouse check loop,
or have your check mouse in your time check loop.

0000:046Ch updates it's self about 18 times a second? (I think?)
You could check into that.
But their is always problems around midnight.
Use a JA or JB condition to check cause JE or JZ may not hit the
exact number and you'll have to loop to get to another try.
And that's a day on the Dword, but you can just use the LO word of it.
MOV AX,[ES:046Ch] ; git the LOword

AH=86h
CX:DX = time to kill in increments of 976
INT 15h
since 0-975 is 976 start with DX=975 and add 976 to it for more
time killing. My tests revieled that if the CX:DX input is off
of a 976 multiple -1 the time kilt is off.

Maybe that will help
Bitdog


Report
Re: How to make a timer? Posted by hlt3000 on 18 Sept 2003 at 10:45 PM
You can do this by intercepting INT 1C, or INT 08, for example, to decrement a counter.
	mov	timer,number_of_seconds
	mov	ax,351ch
	int	21h
	mov	int1cOff,bx
	mov	int1cSeg,es
	mov	ah,25h
	mov	dx,offset int1cProc
	int	21h

Then, you can test any time if the counter has been reset:
timer_loop:
	mov	ax,3
	int	33h
	cmp	cx,mouse_x
	jz	mouse_pos_changed
	cmp	dx,mouse_y
	jz	mouse_pos_changed
	cmp	bx,mouse_btn
	jz	mouse_btn_changed
	mov	ah,1
	int	16h
	jnz	key_pressed
	.
	.
	.
	cmp	timer,0
	jnz	timer_loop

INT 1c would do something like this:
int1cProc:
	pushf
	push	ax
	mov	al,0
	out	70h,al		;read number of seconds
	nop
	in	al,71h
	cmp	al,cs:second
	pop	ax
	jnz	timer_not_0
	dec	cs:timer		;if number of seconds changed, then 
					;decrement cs:timer
	jnz	timer_not_0		;if timer=0
	push	ds			;then restore old vector
	push	0
	pop	ds
	cli
	push	cs:int1cOff
	pop	ds:[1ch*4]
	push	cs:int1cSeg
	pop	ds:[1ch*4+2]
	sti
	pop	ds

timer_not_0:
	popf
	jmp	dword ptr cs:int1cOff



Report
Re: How to make a timer? Posted by Bitdog on 20 Sept 2003 at 1:35 AM

Nice work on the INT 1Ch vector timer.
I hope my added info is accruate.
Hook INT 1Ch it's a user available routine that is simply an IRET
it's called by INT 8 (it's better not to hook INT 8)
Your INT 1Ch routine could just increment a word/Dword in your program
that can be zeroed out at any time by your program then loop untill
you've waited the desired time/increments.
The INT 1Ch de/increments the word 18.2065 times a second er 18hz, not high resolution, but real usefull. So your check CMOS seconds changing
gets checked 18 times per change and only gives you a one second resolution that is often off since your start second doesn't start
exactly on the second change, but might be in the half second,
so if you want to wait one second, you may only wait 1/100000 of a second or less.
But at 18hz, a one second delay could be up to 1/18 second off + or -.
So the simple INT 1Ch increment a Dword, works real well.

Reading CMOS bytes 0-9 should only be done if bit-7 of CMOS byte 10 is clear. Other wise yer reading the BCD bytes 0-9 during a time update cycle and could be wrong.
AAM 16
AAD ; change AL BCD # to unsigned decimal in AL

(I hope that helps somehow.)


Report
Re: A 1/10000 second delay Posted by i2k_flame on 20 Sept 2003 at 12:17 PM
I need a better sample rate than a second, at least 1/1000 of a second. I was using INT 21h with AH set to 2C because it puts 1/100 of second into DL register - but it's still to small. Do the new computers have an interupt that records smaller time increments? I have a realy old book and I couldn't find what INT 1Ch or INT 08h does. I found a website that talks very little about these interupts but that's it:
http://et.nmsu.edu/~etti/winter97/computers/logic/logic.html

What book would you suggest or maybe there is a website?

I don't realy understand the codes u guys gave me, but it seems that you all use a loop to check for change in the timer, right? I suppose there couldn't be any other way. Thanx for your replies.
Report
Re: A 1/10000 second delay Posted by Bitdog on 20 Sept 2003 at 12:42 PM

pctim003.zip
has details on a variety of timer types,
I think it's available here in Programmers Heaven also?
If not, do a www.google.com search for it.
I think there is a previous post (a month old?)
that has a link to pctim003.zip ?

If yer doing Sound Blaster direct mode record/play
you'll want PIT chip info in Ralf Browns INTER61D.ZIP
PIT = Programmable Interval Timer
although pctim003.zip has info on it too.

For a smooth kill time, I've made a proc that checks how many times
the CPU loops in a given time span like 1/18 = one [0000:046Ch] increment
then use that loop count as a kill time loop count.
Increment EAX for a fine resolution,
check the loop time a few times,
and keep/use the highest value, or an average value of the returns.
Using this, different CPU mhz speeds kill the same amount of time,
and the loop count can be inc/dec for a finer resolution.
I had a little running man graphics that ran smooth that way,
where other timers didn't work well at all
since the first time get could be half way through a cycle or more.

TOP: ;recieves CX = kill time count
IN AL,61h ; safely kill a microsecond
JMP SHORT $+2 ; won't jump untill I/O port recovery has occured
LOOP TOP ;this proc is just another try at time killing
RET

gud luk
Bitdog


Report
Re: How to make a timer? Posted by blip on 21 Oct 2003 at 5:39 PM
:
: timer_loop:
: 	mov	ax,3
: 	int	33h
: 	cmp	cx,mouse_x
: 	jz	mouse_pos_changed
: 	cmp	dx,mouse_y
: 	jz	mouse_pos_changed
: 	cmp	bx,mouse_btn
: 	jz	mouse_btn_changed
: 	mov	ah,1
: 	int	16h
: 	jnz	key_pressed
: 	.
: 	.
: 	.
: 	cmp	timer,0
: 	jnz	timer_loop
: 


The INT 33h interface allows you to "install" event handlers for clicks, cursor moves, etc. so polling isn't really required IIRC.
Report
Re: I need a millisecond delay.. Posted by i2k_flame on 22 Oct 2003 at 2:59 PM
Can any one show me a code that makes a millisecond delay?
Report
Re: I need a millisecond delay.. Posted by blip on 22 Oct 2003 at 3:31 PM
This message was edited by Moderator at 2003-10-22 15:31:36

I think this should work.
;NASM code:

Count equ 1193 ;1193182 / 1000 and round.
PIT_Setup equ 10110110b
ModeControlReg equ 43h
TimerCountReg equ 42h

in al,61h ;This turns off the internal speaker b/c we're changing the freq.
and al,~((1<<1) | (1<<0)) ;Clear bits 1 and 0.
out 61h,al

mov al,PIT_Setup ;Get the last PIT counter set up for the count down.
out ModeControlReg,al
mov al,Count & ((1<<8) - 1) ;Get the LSB
out TimerCountReg,al
mov al,Count >> 8 ;Get the MSB
out TimerCountReg,al

Wait:
in al,TimerCountReg
mov bl,al
in al,TimerCountReg
or al,bl
test al,al ;If AL == 0 (both AL and BL were zero), then ZF gets set.
jnz Wait

;...

Report
ahhhh Programming is tough Posted by i2k_flame on 9 Nov 2003 at 8:02 PM
Sorry I don't understand your code. Can you refine it more. Here is a timer I made before all these posts and I need something that could replace those timer blocks with something that can time below a millisecond.
ADD      SP,0100h         ;Setting the stack pointer to 256 bits,
MOV     CX,0005h

label2:
PUSH    CX
MOV     AX,0034h
MOV     DX,0378h
OUT      DX,AX
MOV     AX,0001h         ;This block sends 34h to parallel port
MOV     DX,037Ah
OUT      DX,AX
MOV     AX,000Ch
OUT      DX,AX


MOV     BH,01h
MOV     AH,2Ch
INT       21h
MOV    [DI],DH
label1:                  ;This block is timer #1
INT       21h
SUB      DH,[DI]
CMP     DH,BH
JB       label1


MOV     AX,0048h
MOV     DX,0378h
OUT      DX,AX
MOV     AX,0001h
MOV     DX,037Ah         ;This block sends 48h to parallel port
OUT      DX,AX
MOV     AX,000Ch
OUT      DX,AX


MOV     BH,01h	   ;Set delay to 1 second
MOV     AH,2Ch	   ;Interupt 21 function 2C
INT       21h
MOV    [DI],DH	   ;Copy current time in seconds to memory
label3:                  ;This block is timer #2
INT       21h	   ;Get new time
SUB      DH,[DI}   ;Get time elapsed
CMP     DH,BH	   ;Compare the elapsed time to BH
JB       label3    ;Jump to label3 if DH is smaller than BH


POP      CX
LOOP   label2       ;Loop to the biggining and repeat 5 times

INT      20h



Report
Re: ahhhh Programming is tough Posted by Bitdog on 9 Nov 2003 at 8:58 PM
Have you tried a simple time delaying loop?
TTIME EQU 0xFFFF ;at top of code

MOV CX,TTIME
KILLT:
NOP ;add more NOP instructions, delays more time
LOOP KILLT

Test & deincrement the TTIME amount untill it works fine.

pctim003.zip for sound blaster type PIT & PIC programming.
See Ralf Browns interrupt list for interrupt information.
Both are downloadable on the net, google search.

The code you included used AH=2Ch get current time, DH=seconds
check if second changed is real bad for delay code.
If your program calls just before the seconds change, there isn't much of a delay. Or there could be a full second delay and that's too much time wasted to get anything done in your program.
DL returned is 1/100 of a second.


Report
Re: PCTim Posted by i2k_flame on 10 Nov 2003 at 12:31 AM
Yes, I was reading pctim003.txt 7th chapter and what I know so far is that there are 3 channels. I suppose we can only use the third channel (CTC CHANNEL 2) because it allows to change frequency and it won't change DRAM timings right? But I am not getting how to read the elapsed time from the mode/command register 43h, or where ever it is read from.
It's funny, Bitdog, how u made up a delay with NOP cause we made the same kind of thing but it looks like this:
timer:
MOV   	CX,0EA60h

a10:
MOV   	AX,0EA60h

a20:
DEC    	AX
JNZ     a20

LOOP	a10
RET

It takes about 7 seconds to go through this loop on my machine, AMD 1.4Ghz, about 500 million operations a second, wow. :)
Thanks for all your help, I think sooner or later we will figure out the pctim file, together.
Report
Re: PCTim Posted by Bitdog on 10 Nov 2003 at 2:31 PM
It's been a while since I worked on pctim003.zip and I'm in a project
so I can't go back and write a sound card type IRQ interrupt routine
timer using channel 0 for you. You're kinda on your own, sorry.
If I run into one I'll send it.
For delays longer than a few milli seconds AH=86 INT 15h works well.
Also the 18.2065hz tick timer at 0000:046C is accurate when working
with seconds. (it will only be an eight of a second off max)
Your loop below is not CPU independant for it doesn't check the
loops a CPU can do in a given time, then use that loop count to delay
in your program. There is a recient post on CPU independant delays some where? I use an AMD 1.6gh Duron & 1.4gh Tbird also..

Bitdog




 

Recent Jobs

Official Programmer's Heaven Blogs
Web Hosting | Browser and Social Games | Gadgets

Popular resources on Programmersheaven.com
Assembly | Basic | C | C# | C++ | Delphi | Flash | Java | JavaScript | Pascal | Perl | PHP | Python | Ruby | Visual Basic
© Copyright 2011 Programmersheaven.com - All rights reserved.
Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
Operated by CommunityHeaven, a BootstrapLabs company.