Rnd: Difference between revisions
From NSIS Wiki
Jump to navigationJump to search
m (→Description) |
m (moved Rnd, Rnd64 to Rnd: Removed Rnd64 due to updated calculation not fitting 64bit random result (need an operation resulting in a 128bit number).) |
||
(One intermediate revision by the same user not shown) | |||
Line 22: | Line 22: | ||
ExecWait 'notepad "${tempfile}"' | ExecWait 'notepad "${tempfile}"' | ||
Delete "${tempfile}"</highlight-nsis> | Delete "${tempfile}"</highlight-nsis> | ||
== | == Function == | ||
<highlight-nsis>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | <highlight-nsis>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
;; Generate a random number using the RtlGenRandom api | ;; Generate a random number using the RtlGenRandom api | ||
Line 29: | Line 29: | ||
;; P3 :in: Maximum value | ;; P3 :in: Maximum value | ||
;; min/max P2 and P3 values = -2 147 483 647 / 2 147 483 647 | ;; min/max P2 and P3 values = -2 147 483 647 / 2 147 483 647 | ||
;; max | ;; max range = 2 147 483 647 (31-bit) | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
!define Rnd "!insertmacro _Rnd" | !define Rnd "!insertmacro _Rnd" | ||
Line 45: | Line 45: | ||
Push "$4" ;; random value buffer | Push "$4" ;; random value buffer | ||
IntOp $3 $1 - $0 | IntOp $3 $1 - $0 ;; calculate range | ||
IntOp $3 $3 + 1 | IntOp $3 $3 + 1 | ||
System::Call '*( | System::Call '*(l) i .r4' | ||
System::Call 'advapi32::SystemFunction036(i r4, i 4)' ;; RtlGenRandom | System::Call 'advapi32::SystemFunction036(i r4, i 4)' ;; RtlGenRandom | ||
System::Call '*$4( | System::Call '*$4(l .r1)' | ||
System::Free $4 | System::Free $4 | ||
;; fit value within range | |||
System::Int64Op $1 * $3 | |||
Pop $3 | Pop $3 | ||
System::Int64Op $3 / 0xFFFFFFFF | |||
System::Int64Op $ | |||
Pop $3 | Pop $3 | ||
IntOp $0 $3 + $0 ;; index with minimum value | |||
Pop $4 | Pop $4 |
Latest revision as of 19:45, 7 December 2011
Author: Lloigor (talk, contrib) |
Description
Generates a random number within a range using the RtlGenRandom api.
It can be used as is, or as a random seed generator for other functions, like http://nsis.sourceforge.net/Random. The Microsoft C Runtime Library makes use of this function (RtlGenRandom) in its implementation of "rand_s".
Example
!define tempfile "$EXEDIR\test_output.txt" FileOpen $R0 "${tempfile}" "w" StrCpy $3 0 loop: IntOp $3 $3 + 1 ;-------------------------- ${Rnd} $0 -50000 50000 ;-------------------------- FileWrite $R0 "$0$\r$\n" IntCmp $3 1000 0 loop FileClose $R0 ExecWait 'notepad "${tempfile}"' Delete "${tempfile}"
Function
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Generate a random number using the RtlGenRandom api ;; P1 :out: Random number ;; P2 :in: Minimum value ;; P3 :in: Maximum value ;; min/max P2 and P3 values = -2 147 483 647 / 2 147 483 647 ;; max range = 2 147 483 647 (31-bit) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; !define Rnd "!insertmacro _Rnd" !macro _Rnd _RetVal_ _Min_ _Max_ Push "${_Max_}" Push "${_Min_}" Call Rnd Pop ${_RetVal_} !macroend Function Rnd Exch $0 ;; Min / return value Exch Exch $1 ;; Max / random value Push "$3" ;; Max - Min range Push "$4" ;; random value buffer IntOp $3 $1 - $0 ;; calculate range IntOp $3 $3 + 1 System::Call '*(l) i .r4' System::Call 'advapi32::SystemFunction036(i r4, i 4)' ;; RtlGenRandom System::Call '*$4(l .r1)' System::Free $4 ;; fit value within range System::Int64Op $1 * $3 Pop $3 System::Int64Op $3 / 0xFFFFFFFF Pop $3 IntOp $0 $3 + $0 ;; index with minimum value Pop $4 Pop $3 Pop $1 Exch $0 FunctionEnd