开发者

nasm random number generator function [duplicate]

This question already has answers here: Randomizing Numbers in Assembly with MASM32 开发者_StackOverflow中文版 (3 answers) Closed 4 years ago.

I need a random number generator function written in nasm. I'm sorry for asking, but I couldn't find any!


In many cases a call to rdtsc is enough. Anyway, it depends on your needs. It's perfect when you need a small random number rarely: rdtsc % N, or as seed for more complicate algorithms for other cases.


Among other things, Agner Fog has a random number generator written in assembly, see here.


I don't know NASM, and I'm not in the habit of writing code on demand, unless they pay me.

But, here are algorithms you could investigate:

  • http://en.wikipedia.org/wiki/Pseudorandom_number_generator
  • http://en.wikipedia.org/wiki/Mersenne_twister
  • http://www.codeproject.com/KB/recipes/SimpleRNG.aspx
  • http://www.xkcd.org/221/


; in case you still are looking or for the ones who do look around nowadays, here is my
; experiment on random number generation.
; I hope it will be usefull.

STRUC TIMESPEC
    .tv_sec:    resq    1
    .tv_nsec:   resq    1
ENDSTRUC

STRUC TIMEVAL
    .tv_sec:    resq    1
    .tv_usec:   resq    1
ENDSTRUC

%define tv.tv_sec tv+TIMEVAL.tv_sec
%define tv.tv_usec tv+TIMEVAL.tv_usec
%define ts.tv_sec ts+TIMESPEC.tv_sec
%define ts.tv_nsec ts+TIMESPEC.tv_nsec

    NUMBERCOUNT equ 50
    MAXNUMBER   equ 7
    NUMBERLOOPS equ 50

section .bss

    array   resw    NUMBERCOUNT ; 20 64 bit words to store the numbers
    buffer  resb    1

section .data

ts: ISTRUC TIMESPEC
    at  TIMESPEC.tv_sec,    dq 0
    at  TIMESPEC.tv_nsec,   dq 0
IEND

tv: ISTRUC TIMEVAL
    at  TIMEVAL.tv_sec,     dq 0
    at  TIMEVAL.tv_usec,    dq 0
IEND

section .text

global _start
_start:

; start generating 20 random numbers between 0 and 20 both values included
; we will use the computers timer to obtain a seed and a pseudo random value 

;   call syscall clock_gettime for the seed

    xor r8,r8           ; loops
    inc     r8
repeatLoop:
    inc     r8
    push    r8
    xor rcx, rcx
    mov rdi, array
repeat:
    push    rcx
    push    rdi
    mov rsi, ts
    mov rdi, 0
    mov rax, SYS_CLOCK_GETTIME
    syscall

    mov rsi, 0
    mov rdi, tv
    mov rax, SYS_GETTIMEOFDAY
    syscall

    mov rax,[ts.tv_nsec]
    mov rbx,[tv.tv_usec]

    xor rdx, rdx
    add     rax, rbx
    mov rbx, MAXNUMBER+1
    div rbx

    mov rax, rdx
    xor rdx, rdx
    mov rbx, 10
    div rbx
    add     al,30h
    shl rax, 8
    mov al, dl
    add     al,30h
    pop rdi
    stosw

    pop rcx
    inc rcx
    cmp rcx, NUMBERCOUNT
    jl  repeat

    xor rcx, rcx
    mov rsi, array
repeatGet:  
    xor rax, rax
    lodsw
    push    rcx
    push    rsi
    call    WriteValue
    pop rsi
    pop rcx
    inc rcx
    cmp rcx, NUMBERCOUNT
    jl  repeatGet

    pop r8
    cmp r8,NUMBERLOOPS
    jg  Exit
    call    writeEOL
    jmp repeatLoop

Exit:   
    call    writeEOL
    xor rdi, rdi
    mov rax, SYS_EXIT
    syscall

writeEOL:
    mov al,ASCII_LF
    mov byte[buffer],al
    mov rsi,buffer
    mov rdi,STDOUT
    mov rdx, 1
    mov rax,SYS_WRITE
    syscall
    ret

WriteValue:
    cmp ah,"0"
    jne writeDecimal
    mov ah," "
writeDecimal:   
    mov byte[buffer],ah
    push    rax
    mov rsi,buffer
    mov rdi,STDOUT
    mov rdx, 1
    mov rax,SYS_WRITE
    syscall
    pop rax
writeUnit:
    mov byte[buffer],al
    mov rsi,buffer
    mov rdi,STDOUT
    mov rdx, 1
    mov rax,SYS_WRITE
    syscall
writeSpace:
    mov al," "
    mov byte[buffer],al
    mov rsi,buffer
    mov rdi,STDOUT
    mov rdx, 1
    mov rax,SYS_WRITE
    syscall

    ret


Hi this functions are using the so caled Linear congruential generator(LCG) algorithm, and the parameters are those used by GCC.

section .bss
next: resd 1 ; 32 bits
section .text
_rand:
    mov eax, [next]       ; pass next to eax for multiplication 
    mov ebx, 1103515245   ; the multiplier
    mul ebx               ; eax = eax * ebx
    add eax, 12345        ; the increment 
    mov dword [next], eax ; update next value
    mov ebx, 32768        ; the modulus 
    xor edx, edx          ; avoid Floating point exception
    div ebx               ; edx now holds the random number
    ret                   ; bye
_srand:
    mov eax, 0x0d         ; sys_time
    mov ebx, 0x0          ; NULL
    int 0x80              ; syscall
    mov dword [next], eax ; initialize next
    ret                   ; bye 

the C analog of _rand is something like

static unsigned long int next = 1;
int _rand( void )
{
    next = 1103515245 * next + 12345;
    return next % 32768;
}

and the result of calling _srand is the same as if you would call

srand( time( NULL ));

in C. The range of generated numbers is [0, 32767].

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜