RNG

From: Spam Killer (nospam_at_spamtrap.com)
Date: 03/29/05


Date: Tue, 29 Mar 2005 19:43:34 GMT


; nasm -O2 -g -f elf randtest.asm
; nasm -O2 -g -f elf rand.asm
; ld -o randtest randtest.o rand.o

;; Time-stamp: <05/03/29 21:33:58 wfz> -*-mmx-*-
;; randtest.asm - Testprogram for the Random Number Generator.

; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.

; This program is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; General Public License for more details.

; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

%imacro lcall 1.nolist
        extern %1
        call %1
%endmacro

        global _start

        section .text align=16
_start: fninit
        lcall rseed

        ;; Typical usages

        lcall rnd ; Get a random fraction from [0,1],
                            ; in ST.

        lcall prbg ; Get a random bit in EAX.

        mov ebp,100
        lcall irand ; Get a random number from {0,
                            ; EBP - 1} in EAX.

        mov ebp,1000
        lcall irand1 ; Get a random number from {1,
                            ; EBP} in EAX.

        ;; If wseed is commented out after the first run, the
        ;; sequence will repeat (useful for debugging).

        lcall wseed

exit_ok:xor eax,eax
error: xor eax,-1
        lea ebx,[eax+1]
; sys Exit
        mov eax,1
        int 80h

;; Time-stamp: <2005-03-29 21:35:47 wfz> -*-mmx-*-
;; rand.asm - Random number generator.

Linux equ 80h
Read equ 3
Write equ 4
Open equ 5
Close equ 6
Time equ 13

S_IRUSR equ 400q ; R for owner
O_CREAT equ 100q
%define S_IREAD S_IRUSR
O_RDONLY equ 0
O_WRONLY equ 1

%define d dword
%define q qword

%macro sys 1-7.nolist
%if %0 = 7
  %ifnidn %7,~
        mov ebp,%7
  %endif
%endif

%if %0 > 5
  %ifnidn %6,~
        mov edi,%6
  %endif
%endif

%if %0 > 4
  %ifnidn %5,~
        mov esi,%5
  %endif
%endif

%if %0 > 3
  %ifnidn %4,~
        mov edx,%4
  %endif
%endif

%if %0 > 2
  %ifnidn %3,~
        mov ecx,%3
  %endif
%endif

%if %0 > 1
  %ifnidn %2,~
        mov ebx,%2
  %endif
%endif
%ifidn %1,Times
%assign %1 25
%endif
%ifidn %1,Pause
%assign %1 29
%endif
%ifidn %1,Lock
%assign %1 53
%endif
        mov eax,%1
        int Linux
%endmacro

%imacro pushm 1-*.nolist
%rep %0
        push %1
%rotate 1
%endrep
%endmacro

%imacro popm 1-*.nolist
%rep %0
        pop %1
%rotate 1
%endrep
%endmacro

%imacro proc 1-2.nolist
%ifidn %2,private
%else
        global %1
%endif ; private
%1 resb 0
%endmacro

%imacro endp 0-1
%endmacro

        section .text align=16

; Calling sequence: call srand
; Entry conditions: EDX:EAX = Random seed.
; Exit conditions: X <- seed.

proc srand
        mov [X],eax
        mov [X+4],edx
        ret
endp srand

; Calling sequence: call rseed
; Entry conditions: None.
; Exit conditions: EDX:EAX <- X <- Random seed from date and time.

        align 16
proc rseed
        pushm ebx,ecx
        sys Open, rfile, O_RDONLY, S_IREAD
        test eax,eax
        js .1
        mov [fd],eax
        sys Read, [fd], X, 8
        test eax,eax
        js .1
        sys Close, [fd]
        jmp .2
.1: sys Time, X
.2: mov eax,d[X]
        mov edx,d[X+4]
        popm ecx,ebx
        ret
endp rseed

; Calling sequence: lcall rand
; Entry conditions: None.
; Exit conditions: EDX:EAX <- Random Number.

        align 16
proc rand
        push ebx
        mov eax,d[X]
        mov ebx,d[X+4]
        mul d[a] ; lo lo
        imul ebx,d[a] ; hi lo
        add ebx,edx ; + carry
        mov edx,d[X]
        imul edx,d[a+4] ; lo hi
        add edx,ebx ; + carry
        add eax,1
        adc edx,0
        mov d[X],eax
        mov d[X+4],edx
        pop ebx
        ret ; np 2 2
endp rand

; Calling sequence: call rnd
; Entry conditions: None.
; Exit conditions: ST <- Random fraction from [0,1].

        align 16
proc rnd
        pushm eax,edx
        fnstcw [CW_temp]
        fldcw [CW_zero]
        call rand
        add edx,edx
        jnc .1
        shr edx,1
        mov d[temp],eax
        mov d[temp+4],edx
        fild q[temp]
        fadd q[@2_63]
        jmp .2
.1: fild q[X]
.2: fmul q[@r2_64]
        fldcw [CW_temp]
        popm edx,eax
        ret
endp rnd

; Calling sequence: call prbg
; Entry conditions: None.
; Exit conditions: EAX <- Random bit.
        
        align 16
proc prbg
        push edx
        call rand
        xor eax,eax
        add edx,edx
        adc eax,0
        pop edx
        ret
endp prbg

; Calling sequence: call irand
; Entry conditions: EBP = RANGE.
; Exit conditions: EAX <- Random number from {0,RANGE-1}.

        align 16
proc irand
        pushm ebx,edx
        call rand
        mov ebx,edx
        mul ebp
        mov eax,ebx
        mov ebx,edx
        mul ebp
        add eax,ebx
        adc edx,0
        mov eax,edx
        popm edx,ebx
        ret
endp irand

; Calling sequence: call irand1
; Entry conditions: EBP = RANGE.
; Exit conditions: EAX <- Random number from {1,RANGE}

        align 16
proc irand1
        push edx
        call rand
        mov eax,edx
        mul ebp
        lea eax,[edx+1]
        pop edx
        ret
endp irand1

; Calling sequence: call rrand
; Entry conditions: None.
; Exit conditions: EDX:EAX <- Minv of last number.

        align 16
proc rrand
        push ebx
        mov eax,d[X]
        mov ebx,d[X+4]
        sub eax,1
        sbb ebx,0
        mul d[mia] ; lo lo
        imul ebx,d[mia] ; hi lo
        add ebx,edx ; + carry
        mov edx,d[X] ; hi lo
        dec edx
        imul edx,d[mia+4]
        add edx,ebx
        mov d[X],eax
        mov d[X+4],edx
        pop ebx
        ret ; np 2 2
endp rrand

; Calling sequence: call irrand1
; Entry conditions: EBP = RANGE.
; Exit conditions: EAX <- Random number from {1,RANGE}.

        align 16
proc irrand1
        push edx
        call rrand
        mov eax,edx
        mul ebp
        lea eax,[edx+1]
        pop edx
        ret
endp irrand1

; Calling sequence: call wseed
; Entry conditions: None
; Exit conditions: Last X saved to rseed.bin

        align 16
proc wseed
        pushm eax,ebx,ecx,edx
        sys Open, rfile, O_CREAT | O_WRONLY, 666q
        test eax,eax
        js .1
        mov [fd],eax
        sys Write, [fd], X, 8
        sys Close, [fd]
.1: popm edx,ecx,ebx,eax
        ret
endp wseed

        section .data
X dd 1, 0
a dd 4c957f2dh, 5851f42dh ; 6364136223846793005
mia dd 329e28a5h, 0c097ef87h ; 13877824140714322085
@2_63 dq 9223372036854775808.0
; @2_64 dq 18446744073709551616.0
@r2_64 dd 0, 3bf00000h
CW_zero dw 0000111101111111b
rfile db "/home/wfz/.rseed.bin", 0

        section .bss
temp resq 1
fd resd 1
CW_temp resw 1