;; RANDOM.ASM--implementation of minimal standard random number
;; generator. See article by David G. Carta, CACM Jan 1990, p. 87
;;
;; Calling Sequence:
;;
;; EXTRN Random: NEAR
;; call Random
;; 0 < value < 2**31 - 1 returned in dx|ax
;;
;; Assumes seed has been set elsewhere as a PUBLIC double-word
;; Assumes ds is set to @data.
;;
;; Program text from "Assembly Language for the IBM PC Family" by
;; William B. Jones, (c) Copyright 1992, 1997, Scott/Jones Inc.
;;
.MODEL SMALL
.DATA
EXTRN Seed:DWORD ; set by caller
A EQU 16807
S0 EQU WORD PTR Seed ; Low order word of seed
S1 EQU WORD PTR Seed+2 ; High order word of seed
.CODE
PUBLIC Random
Random PROC
;
; P2|P1|P0 := (S1|S0) * A
;
mov ax, S0
mov bx, A
mul bx
mov si, dx ; si := pp01 (pp = partial product)
mov di, ax ; di := pp00 = P0
mov ax, S1
mul bx ; ax := pp11
add ax, si ; ax := pp11 + pp01 = P1
adc dx, 0 ; dx := pp12 + carry = P2
;
; P2|P1:P0 = p * 2**31 + q, 0 <= q < 2**31
;
; p = P2 SHL 1 + sign bit of P1 --> dx
; (P2:P1|P0 < 2**46 so p fits in a single word)
; q = (P1 AND 7FFFh)|P0 = (ax AND 7fffh) | di
;
shl ax, 1
rcl dx, 1
shr ax, 1
;
; dx:ax := p + q
;
add dx, di ; dx := p0 + q0
adc ax, 0 ; ax := q1 + carry
xchg ax, dx
;
; if p+q < 2**31 then p+q is the new seed; otherwise whack
; off the sign bit and add 1 and THATs the new seed
;
test dx, 8000h
jz Store
and dx, 7fffh
add ax, 1 ; inc doesn't set carry bit
adc dx, 0
Store:
mov S1, dx
mov S0, ax
ret
Random ENDP
END
Assembly: How do I seed this random number generator?
This random number generator is working like it's supposed to, but it's giving me the same sequence of numbers each time I run it because I can't figure out how to seed it. I read the author's notes ("Assumes seed has been set elsewhere as a PUBLIC double-word"), but I don't know enough to get that to work. I'm using tasm and tlink. Lemme know if you need more specific information.
Are you declaring a variable named 'seed' anywhere? If not, it shouldn't link because it says there is such a variable and it uses it but it doesn't declare that variable.
If so, just setting the variable should seed it to whatever you want. To get different sequences each run, just set it to the time or something.
If so, just setting the variable should seed it to whatever you want. To get different sequences each run, just set it to the time or something.
.datapublic Seed:DwordSeed dd 0 ;seed <== change to change the seed of the random function..code;akamov word ptr [Seed], 0010h ;lowordmov word ptr [Seed+2], 0005h ;hiword;makes 00050010h
To be able to link a routine with a high-level language, you have to put the code and data in the proper segments, which means knowing how the language declares its segments and groups. For example, Borland code segments are named _TEXT. Shared identifiers must be made PUBLIC where they are defined, and EXTRN where they are used but not defined. These identifiers appear in the .OBJ files produced by assemblers and compilers, and the linker matches them up. (A Tale of Two Assemblers)
How are you calling the code?
To Extrarius:
Yeah, I'd like to seed it to time, I think I know how once I can get it let me (int 1Ah, right?).
To Washu:
That's what I was trying before I think. I tried it again but it's telling me there's 'extra characters on line'. I have no idea why it's telling me that though. I copied it just like you had.
To Igni:
I think I know what you mean.
EXTRN Random: NEAR (In the .CODE before the main PROC)
when I call it:
call Random
I would post my code but it's very long and only bout 70% done though it does assemble.
Anyway thanks for the quick replies. I'm gonna keep trying.
Well, you're not supposed to take it literally, it was just "sample" code, but the public line is probably wrong. Should probably just be public seed.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement