[英]Pseudorandom generator in Assembly Language
我需要一个伪随机数生成器算法用于课程中分配的汇编程序,我更喜欢一个简单的算法。 但是,我不能使用外部库。
什么是一个好的,简单的伪随机数生成器算法用于汇编?
容易的是只选择两个大的相对素数a和b,然后将你的随机数乘以a并加上b。 使用模运算符将低位保持为随机数,并保留下一次迭代的完整值。
该算法称为线性同余生成器 。
计算机编程艺术的第2卷有很多关于伪随机数生成的信息。 算法在汇编程序中演示,因此您可以自己查看汇编程序中最简单的算法。
但是,如果您可以链接到外部库或目标文件,那将是您最好的选择。 然后你可以链接到,例如, Mersenne Twister 。
请注意,大多数伪随机数生成器对于加密并不安全,因此如果您需要生成安全随机数,则需要超越基本算法(并且可能应该使用特定于操作系统的加密API)。
简单的测试代码,不要与Crypto一起使用
从测试计算机软件,页面138
如果是32位数学,则不需要操作MOD 2^32
RNG = (69069*RNG + 69069) MOD 2^32
好吧 - 因为我没有看到对旧的线性反馈移位寄存器的引用,我发布了一些基于SSE内在的C代码。 只是为了完成。 几个月前我写了那篇文章来再次提高我的SSE技能。
#include <emmintrin.h>
static __m128i LFSR;
void InitRandom (int Seed)
{
LFSR = _mm_cvtsi32_si128 (Seed);
}
int GetRandom (int NumBits)
{
__m128i seed = LFSR;
__m128i one = _mm_cvtsi32_si128(1);
__m128i mask;
int i;
for (i=0; i<NumBits; i++)
{
// generate xor of adjecting bits
__m128i temp = _mm_xor_si128(seed, _mm_srli_epi64(seed,1));
// generate xor of feedback bits 5,6 and 62,61
__m128i NewBit = _mm_xor_si128( _mm_srli_epi64(temp,5),
_mm_srli_epi64(temp,61));
// Mask out single bit:
NewBit = _mm_and_si128 (NewBit, one);
// Shift & insert new result bit:
seed = _mm_or_si128 (NewBit, _mm_add_epi64 (seed,seed));
}
// Write back seed...
LFSR = seed;
// generate mask of NumBit ones.
mask = _mm_srli_epi64 (_mm_cmpeq_epi8(seed, seed), 64-NumBits);
// return random number:
return _mm_cvtsi128_si32 (_mm_and_si128(seed,mask));
}
将此代码转换为汇编程序是微不足道的。 只需用真正的SSE指令替换内在函数,并在其周围添加一个循环。
顺便说一下 - 此代码生成的序列在4.61169E + 18个数字后重复。 这比通过素数方法和32位算术获得的要多得多。 如果展开它也会更快。
为什么不使用外部库? 那个轮子已经发明了几百次,为什么要再这样做呢?
如果您需要自己实施RNG,您是否需要按需生成数字 - 即您是否实现了rand()函数 - 或者您是否需要生成随机数流 - 例如用于内存测试?
你需要一个加密的RNG吗? 它重复前需要多长时间? 你是否必须绝对,积极地保证所有位的均匀分布?
这是几年前我用过的简单黑客。 我在嵌入式工作,我需要在上电时测试RAM,我想要非常小,快速的代码和很少的状态,我这样做了:
这需要非常少的代码(尽管你需要一个crc32函数的表)并且状态很少,但是psuedorandom输出流在重复之前有很长的循环时间。 此外,它不需要处理器上的SSE。 假设你有方便的CRC32功能,实现起来很简单。
使用masm615编译器:
delay_function macro
mov cx,0ffffh
.repeat
push cx
mov cx,0f00h
.repeat
dec cx
.until cx==0
pop cx
dec cx
.until cx==0
endm
random_num macro
mov cx,64 ;assum we want to get 64 random numbers
mov si,0
get_num:
push cx
delay_function ;since cpu clock is fast,so we use delay_function
mov ah,2ch
int 21h
mov ax,dx ;get clock 1/100 sec
div num ;assume we want to get a number from 0~num-1
mov arry[si],ah ;save to array you set
inc si
pop cx
loop get_num ;here we finish the get_random number
@jjrv
你所描述的实际上是一个线性的同构发生器。 最随机的位是最高位。 要从0..N-1获得一个数字,您可以将整数乘以N(32位乘32位给出64位)并使用高32位。
你不应该只使用任何的编号为 (乘数从一个全值到下一个进步),在高德纳推荐号(表1 3.3.4节TAOCP第2卷1981)是1812433253,1566083941,69069和1664525。
您可以为b选择任何奇数。 (补充)。
你也可以在不同的位之间模拟具有XOR和元素的移位寄存器,这将为你提供伪随机数字序列。
线性同余(X = AX + C mod M)PRNG可能是一个很好的分配给汇编程序课程,因为你的学生将不得不处理2 ^ 31的中间AX结果的进位和计算模数。 如果您是学生,他们可以直接在汇编程序中实施,也可能是讲师的想法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.