I've glanced through disassembly of the Int 0x1a handler on my computer. It seems to be reading the time from 0040:006c. A google search confirmed that this is not unique to my computer.
Therefore, it is possible to implement my previous program entirely in QBASIC 1.1, without any usage of assembly.
I must emphasize that I have barely tested the various sub procedures of this program, other than to verify that the first 16 results from rand match MSVCRT's results using a seed of 1.
It seems that the first iteration of rand results in poor randomness when compared with similar seeds.
Note that the timer dword is read as 4 bytes individually. It is possible for the value to change while it is being read. This is okay, since it is only used to seed the pseudorandom number generator.
I intend to verify the correctness of the various sub procedures within the next few days. Even if they are already correct, I might tweak the code a little.
Regards,
Michael
P.S. I think it is elegant the way I emulate assembly instructions and syntax within QBASIC.
-------------------------------- rand1.bas
'public domain, augest 2011, michael calkins
'assumes that there is a dword timer value at 0x0040:0x006c
'minimally tested (minimally is an overstatement)
'no guarantees of correctness of any of the procedures.
'if you find any mistakes, please let me know.
DECLARE SUB srandwithtimer ()
DECLARE SUB rand ()
DECLARE SUB add (a AS LONG, b AS LONG)
DECLARE SUB mul (a AS LONG, b AS LONG)
DECLARE SUB shl (a AS LONG, b AS INTEGER)
DECLARE SUB shr (a AS LONG, b AS INTEGER)
DIM SHARED seed AS LONG
DIM SHARED result AS INTEGER
DIM p(0 TO 25) AS INTEGER
seed = 1
CLS
srandwithtimer
FOR i = 0 TO 25
p(i) = i
NEXT
FOR i = 0 TO 25
DO
rand
LOOP UNTIL result <= &H7FF7
SWAP p(i), p(result MOD 26)
NEXT
FOR i = 0 TO 25
PRINT CHR$(p(i) + &H61);
NEXT
PRINT
SYSTEM
SUB add (a AS LONG, b AS LONG)
DIM x AS LONG
DIM y AS LONG
DIM c AS INTEGER
x = (a AND &HFFFF&) + (b AND &HFFFF&)
y = b
shr a, &H10
shr y, &H10
a = a + y - (x > &HFFFF&)
shl a, &H10
a = a OR (x AND &HFFFF&)
END SUB
SUB mul (a AS LONG, b AS LONG)
DIM t AS LONG
DIM i AS INTEGER
t = a
a = 0
FOR i = 0 TO &H1E
IF b AND (2 ^ i) THEN add a, t
shl t, 1
NEXT
IF b AND &H80000000 THEN add a, t
END SUB
SUB rand
mul seed, 214013
add seed, 2531011
result = (seed AND &H7FFF0000) \ &H10000
END SUB
SUB shl (a AS LONG, b AS INTEGER)
a = ((a AND ((2 ^ (&H1F - b)) - 1)) * (2 ^ b)) OR (&H80000000 AND ((a AND (2 ^ (&H1F - b))) <> 0))
END SUB
SUB shr (a AS LONG, b AS INTEGER)
a = ((a AND &H7FFFFFFF) \ (2 ^ b)) OR ((2 ^ (&H1F - b)) AND ((a AND &H80000000) <> 0))
END SUB
SUB srandwithtimer
DEF SEG = &H40
seed = PEEK(&H6D) OR (PEEK(&H6E) * &H100&) OR (PEEK(&H6F) * &H10000)
shl seed, 4
seed = seed OR PEEK(&H6C)
END SUB
This message has been edited by MCalkins on Aug 31, 2011 3:21 AM