汇编语言中的伪随机生成器

时间:2008-09-18 05:07:50

标签: algorithm assembly prng

我需要一个伪随机数生成器算法用于课程中分配的汇编程序,我更喜欢一个简单的算法。但是,我不能使用外部库。

什么是用于汇编的好的,简单的伪随机数生成器算法?

9 个答案:

答案 0 :(得分:8)

简单的一个就是选择两个大的相对素数a和b,然后将你的随机数乘以a并加上b。使用模运算符将低位保留为随机数,并保留下一次迭代的完整值。

此算法称为linear congruential generator

答案 1 :(得分:3)

The Art of Computer Programming的第2卷有很多关于伪随机数生成的信息。算法在汇编程序中演示,因此您可以自己查看汇编程序中最简单的算法。

如果你可以链接到外部库或目标文件,那将是你最好的选择。然后,您可以链接到,例如Mersenne Twister

请注意,大多数伪随机数生成器对加密是安全的,因此如果您需要生成安全随机数,则需要超越基本算法(并且可能应该使用特定于操作系统的加密API )。

答案 2 :(得分:3)

简单的测试代码,不要与Crypto一起使用

来自测试计算机软件,页面138

如果是32位数学,则不需要操作MOD 2^32

RNG = (69069*RNG + 69069) MOD 2^32

答案 3 :(得分:2)

好吧 - 由于我没有看到对旧的线性反馈移位寄存器的引用,我发布了一些基于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指令替换内在函数,并在其周围添加一个循环。

Btw - 此代码生成的序列在4.61169E + 18个数字后重复。这比通过素数方法和32位算术获得的要多得多。如果展开它也会更快。

答案 4 :(得分:1)

@jjrv
你所描述的实际上是一个线性的同构发生器。最随机的位是最高位。要从0..N-1获得一个数字,你可以将整个值乘以N(32位乘以32位给出64位)并使用高32位。

 你不应该只使用 a 的任何数字(从一个完整值到下一个完整值的乘数),Knuth推荐的数字(表1第3.3.4节TAOCP第2卷,1981年)是1812433253 ,1566083941,69069和1664525。

你可以选择 b 的任何奇数。 (补充)。

答案 5 :(得分:1)

为什么不使用外部库?那个轮子已经发明了几百次,为什么要再次发明呢?

如果您需要自己实施RNG,您是否需要按需生成数字 - 即您是否正在实施rand()函数 - 或者您是否需要生成随机数的流 - 例如进行内存测试?

你需要一个加密的RNG吗?它重复前需要多长时间?你是否必须绝对,积极地保证所有位的均匀分布?

这是几年前我用过的简单黑客。我在嵌入式工作,我需要在上电时测试RAM,我想要非常小,快速的代码和很少的状态,我这样做了:

  • 从种子的任意4字节常量开始。
  • 计算这4个字节的32位CRC。这将为您提供接下来的4个字节
  • 将这4个字节反馈到CRC32算法中,就像它们已被追加一样。这8个字节的CRC32是下一个值。
  • 只要你想重复。

这需要很少的代码(尽管你需要一个crc32函数的表)并且状态很少,但是psuedorandom输出流在重复之前有很长的循环时间。此外,它不需要处理器上的SSE。假设你有方便的CRC32功能,实现起来很简单。

答案 6 :(得分:1)

使用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 

答案 7 :(得分:0)

你也可以在单独的位之间模拟具有XOR和元素的移位寄存器,这将给出伪随机数字序列。

答案 8 :(得分:0)

线性同余(X = AX + C mod M)PRNG可能是一个很好的分配给汇编程序课程,因为你的学生必须处理2 ^ 31的中间AX结果的进位并计算模数。如果你是学生,他们可以直接用汇编语言实现,也可能是讲师的想法。