;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%; ; ГЕНЕРАТОР СЛУЧАЙНОГО ЧИСЛА V. 0.42 (x) 2005 СЛОН ; ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%; ; Интервал: [0..eax-1] ; ;------------------------------------------------------------------------------; ; Используется алгоритм ГПСЧ Джорджа Марсаглии - "Xorshift - 128" ; ; Данный алгоритм прошел тест DIEHARD его период 2^128-1 ; ;------------------------------------------------------------------------------; ; Использование: call r_init ; ; mov eax,ГРАНИЦА ИНТЕРВАЛА ; ; call brandom32 ; ;------------------------------------------------------------------------------; ; Результат: число в интервале [0..ГРАНИЦА ИНТЕРВАЛА] ; ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%; ;----[Подпрограмма инициализации генератора случайных чисел]-------------------; r_init: push ebp eax edx ; Сохраняем в стэке ebp,eax,edx call __delta1_ ; __delta1_: pop ebp ; Получение дельта смещения sub ebp,offset __delta1_ ; db 0fh,031h ; Получаем случайное зерно mov [ebp+x],eax ; pop edx eax ebp ; Восстанавливаем edx,eax,ebp ret ; Возврат из подпрограммы ;----[Подпрограмма генерации случаного чмсла в диапазоне]----------------------; brandom32: ; Эта подпрограмма ; возвращает случайное число ; в диапазоне 0..eax-1 push edx ecx ebp ; Сохраняем в стэке edx,ecx,ebp call __delta2_ ; __delta2_: pop ebp ; Получение дельта смещения sub ebp,offset __delta2_ ; imul eax,eax,100 ; Умножаем eax на 100 push eax ; и сохраняем eax в стэке call random32 ; Вызываем подпрограмму ; генерации случайного числа xor edx,edx ; Обнуляем edx pop ecx ; Восстанавливаем значение ; из стэка в ecx div ecx ; Делим eax на ecx xchg eax,edx ; Помещаем остаток в eax xor edx,edx ; Обнуляем edx push 100 ; Помещаем в ecx - 100 pop ecx ; div ecx ; Делим eax на ecx pop ebp ecx edx ; Восстанавливаем ebp,ecx,edx, ret ; Возврат из подпрограммы ;----[Подпрограмма генерации случайного числа]---------------------------------; random32: push ebx edx ecx ; push ebp ; Сохраняем регистры в стэке call __delta3_ ; __delta3_: pop ebp ; Получение дельта смещения sub ebp,offset __delta3_ ; mov eax,12345678 ; x = dword ptr $-4 ; shl eax,0bh ; Выполняем математические xor eax,[ebp+x] ; преобразования по нужному нам mov edx,362436069 ; алгоритму данная часть y = dword ptr $-4 ; выглядела бы на С так: mov [ebp+x],edx ; unsigned long x=123456789, mov ecx,521288629 ; y=362436069, z = dword ptr $-4 ; z=521288629, mov [ebp+y],ecx ; w=88675123; mov ebx,88675123 ; t=(x^(x<<11));x=y;y=z;z=w; w = dword ptr $-4 ; Где t в нашем случае eax mov [ebp+z],ebx ; mov edx,[ebp+w] ; Далее идут следующие shr edx,13h ; вычисления, которые дают СЧ xor edx,[ebp+w] ; (w=(w^(w>>19))^(t^(t>>8))); xor edx,eax ; shr eax,08h ; xor edx,eax ; mov [ebp+w],edx ; mov eax,edx ; pop ebp ; pop ecx edx ebx ; Вынимаем регистры из стэка retn ; Возврат из подпрограммы