Here is an axiom that I wrote a while ago to deal with 4 byte numbers and timekeeping. It uses the system clock so it is accurate to the second. If you need fractions of a second, you will have to use interrupts.
Commands:
All commands are located under Vars->Window->T/Theta or U/V/W
Time:
ClkOn //Starts the system clock if it isn't running already.
ClkOff //Stops the system clock and sets it to 0. If you want to zero the clock, just turn it off and back on. Note that this resets the user's on-calc clock as well. Not that anyone really cares...
GetTime(oPtr) //Sets the 4 bytes pointed to to the current time in seconds. If you are expecting time to be less than 16 hours, you can just read the first two bytes of that. For example you can do GetTime(oA) and then just read A to get the time passed in seconds. (Although doing so will modify B as well)
4 byte math:
Although you didn't ask for this, Ill document it anyway since there is a lot of 4 byte math commands in the axiom.
All commands return their first argument.
Add(oPtr1, oPtr2) //Adds the number pointed to by oPtr2 to oPtr1. oPtr2 is unchanged. Like all 4 byte commands, this returns the first argument, oPtr1.
Add(oPtr1) //Increments the 4 byte value pointed to.
Sub(oPtr1, oPtr2) //The same as Add( but subtracts the numbers instead. oPtr2 is unchanged.
Sub(oPtr1, oPtr2)r //Returns the sign of the subtraction operation. Basically it returns 1 if the value pointed to by oPtr1 is greater than oPtr2, 0 if they are equal and -1 (65536) if oPtr2 is greater. The contents of oPtr1 and oPtr2 are unchanged
Sub(oPtr1) //Decrements the value pointed to.
Ld(oPtr1, oPtr2) //Sets the value pointed to by oPtr1 to the value pointed to byo Ptr2. Basically {oPtr2}r->{oPtr1}r:{oPtr2+2}r->{oPtr1+2}r
Ld(oPtr1, low, high) //Loads the value of low, high into oPtr1. Basically low->{oPtr1}r:high->{oPtr1+2}r
Ld(low, high)r //Loads the value of low, high into a temporary spot and returns the pointer to it. Useful if you want to do a constant operation (like adding 285 to a number) but don't want to have a dedicated scrap area of memory for it. There can only be one at a time so make sure you aren't using the value of the last one before using another.
Ld(oPtr1)r //Sets the 4 byte value pointed to by Ptr1 to 0
Mul2(oPtr1) //Multiplies the value pointed to by oPtr1 by 2. Like all 4 byte commands, it returns a pointer to its first argument, oPtr1. This means that doing Mul2(Mul2(oPtr1)) is a good way of multiplying by 4
Div2(oPtr1) //Works the same way as Mul2 but divides by 2 instead.
Mul(oPtr1, oPtr2) //Multiplies oPtr1 by oPtr2. Unlike other commands, this modifies oPtr2. You have been warned.
Div(oPtr1, oPtr2) //Divides oPtr1 by oPtr2. Unlike other commands, this modifies oPtr2.
Div()r //Returns the pointer to the remainder of the last Div(oPtr1, oPtr2) operation.
_min(oPtr1, oPtr2) //Returns the pointer to the smaller of oPtr1 and oPtr2. This leaves both oPtr1 and oPtr2 unchanged. (but the result returned will be either oPtr1 or oPtr2)
_max(oPtr1, oPtr2) //Returns the pointer to the larger of oPtr1 and oPtr2.
If you need a routine to display 4 byte values, I can share my text axiom.