%include "CONSTANTS.h" MAX_SIZE equ 10 MAX_VALUE equ 100 ; for the RNG, glibc values A EQU 1103515245 M EQU 70000000h C EQU 12345 section .data ; global seed for the rng RNG_SEED dq 1 rngTestFmt: db `The new rng value is %d\n`,0 rngTestFmt2: db `%d occured %d times\n`,0 fmt1: db `\n\ntesting %d to %d %d times\n`,0 fmt2: db `\n\nTesting distribution of a d20\n`,0 section .bss array: resq MAX_SIZE section .text global main main: ; init the RNG mov RAX, 100 ; 100 is the time system call mov rdi, 0 ; the only argument is nullptr syscall ; the time will be stored in rax. mov qword[RNG_SEED], rax mov rdi, fmt1 mov rsi, 20 mov rdx, 30 mov rcx, 15 call CallPrintf mov rdi, 15 mov rsi, 20 mov rdx, 30 call SIMPLE_RNG_TEST mov rdi, fmt2 call CallPrintf call COMPLEX_RNG_TEST jmp Exit SIMPLE_RNG_TEST: ; this will just print n random values between low and high ; rdi the first parameter will hold n ; rsi the second parameter will hold low ; rdx the third parameter will hold high ; ; I need to have ; r12 the lcv 0 to n-1 ; r13 the range rdx - rsi ; r14 the low value ; prolog push rbp mov rbp, rsp ; save the perm registers push r12 push r13 push r14 ; save rdi at the bottom of the stack ; consider this a local variable push rdi ; r13 = max mov r13, rdx ; r13 = max - min sub r13, rsi ; r14 = min mov r14, rsi ; base of rng ; i = 0; mov r12,0 SIMPLE_RNG_LOOP_TOP: ; while i < min cmp r12, qword [rsp] je SIMPLE_RNG_LOOP_BOTTOM mov rdi, r13 mov rsi, r14 call RAND_IN_RANGE mov rdi, rngTestFmt mov rsi, rax call CallPrintf inc r12 jmp SIMPLE_RNG_LOOP_TOP SIMPLE_RNG_LOOP_BOTTOM: ; epilogue ; remember, we stuck rdi on the stack to store it. pop rdi ; restore the perm registers pop r14 pop r13 pop r12 pop rbp ret COMPLEX_RNG_TEST: ; this will test my rng. ; I will generate 1000 values between 0 and 19 ; and hope that they each show up the same "number of times" ; ; I will use r12 as my index, so I need to save that. ; I will use r13 to hold the base address of my array ; prologue ; save the base pointer and fix the stack pointer push rbp mov rbp, rsp ; save the permanant registers I wish to use push r12 push r13 ; i need a local array, so increment the stack pointer by this amount sub rsp, (20+1) * 8 mov r13, rsp mov r12, 0 TOP_OF_INIT_LOOP: cmp r12, 20 jg OUT_OF_INIT_LOOP mov qword [r12*8 + r13],0 inc r12 jmp TOP_OF_INIT_LOOP OUT_OF_INIT_LOOP: mov r12, 0 TOP_OF_GENERATE_LOOP: cmp r12, 10000 je PRINT_RESULTS mov rdi, 20 mov rsi, 0 call RAND_IN_RANGE inc qword [r13 + 8 *rax] inc r12 jmp TOP_OF_GENERATE_LOOP PRINT_RESULTS: mov r12, 0 TOP_OF_PRINT_LOOP: cmp r12, 20 je EXIT_FUNCTION mov rdi, rngTestFmt2 mov rsi, r12 mov rdx, [r13 + r12 * 8] call CallPrintf inc r12 jmp TOP_OF_PRINT_LOOP EXIT_FUNCTION: ; epilogue ; eliminate the local array, decrement put the stack pointer back add rsp, (20+1) * 8 ; restore the permenant registers pop r13 pop r12 ; restore the base pointer pop rbp ret RAND_IN_RANGE: ; this function will generate a random number in a range. ; Input: rdi: parameter 1: the size of the range ; rsi: parameter 2: the min value ; ; Output: rax: the value ; ; So this should do rand() % size + minValue ; ; This is not a leaf routine, so I will need to save rdi and rsi ; Well not really, beacuse RAND (below) does not use these, but. ; preamble push rbp mov rbp, rsp push rsi push rdi call RAND ; rax will now hold the random number, ; I need to mod this by rdi pop rdi mov rdx, 0 div rdi ;rdx will now hold the remaind ; I need to add rsi to it pop rsi add rdx, rsi ; place the final answer in rax mov rax, rdx ; epilogue pop rbp ret RAND: ; rng, see https://en.wikipedia.org/wiki/Linear_congruential_generator ; we could use the system call, but we need some functions ; seed_new = (seed_old * a + c ) % m ; ; we will put use the global RNG_SEED for the see, ; this is the default behaviaor ; we will need to use rax, rdx, for computations ; we will return the value in rax ; ; This is a leaf node, so we can be very sloppy here ; in fact, there is no need to build an activation record ; mov rax, [RNG_SEED] mov rbx, A mov rdx, 0 mul rbx add rax, C mov rbx, M div rbx mov rax, rdx mov [RNG_SEED], rax ret