Blog. Just Blog
Еще один генератор случайных чисел на Ассемблере
В закромах Родины нашлась реализация еще одного генератора случайных чисел. Он более громоздкий, чем минимальный генератор Парка-Миллера, использует операции с плавающей точкой и кольцевой буфер, но результаты выдает гораздо лучше. Кроме большого кода ему также требуется больше места и в сегменте данных:Code (Assembler) : Убрать нумерацию
- section '.data' data readable writeable
- ; Данные для генератора случайных чисел
- JJ = 10 ; lag 1
- KK = 17 ; lag 2, size of circular buffer
- R1 = 19 ; rotate count
- R2 = 27 ; rotate count
- randp1 dt 1.5 ; used for conversion to float
- dw 0 ; alignment
- p1 dd 0 ; pointer in circular buffer
- p2 dd 0 ; pointer in circular buffer
- randbuf dd (2*KK) dup(?) ; circular buffer
Code (Assembler) : Убрать нумерацию
- ; Инициализация генератора случайных чисел
- invoke GetTickCount
- stdcall WRandomInit,eax
- ...
Code (Assembler) : Убрать нумерацию
- ; Получить случайное число
- stdcall WRandom
- ; В регистрах EDX:EAX случайное число
- ...
- ; Получить случайное число от 1000 до 100000
- stdcall WIRandom,1000,100000
- ; В регистре EAX случайное число
- ...
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; Получить случайное число
- ; stdcall WRandom
- ; на выходе EDX:EAX - случайное число
- ;---------------------------------------------
- proc WRandom
- stdcall WBRandom
- or edx, 80000000h
- mov dword [randp1],eax
- mov dword [randp1+4],edx
- fld1
- fld [randp1]
- ret
- endp
- ;---------------------------------------------
- ; Получить случайное число в нужном интервале
- ; stdcall WIRandom,min,max
- ; на выходе EAX - случайное число
- ; EAX=80000000h - ошибка
- ;---------------------------------------------
- proc WIRandom rmin:dword,rmax:dword
- push ebx
- stdcall WBRandom
- ; Проверить корректность задания границ, MIN<MAX
- mov ebx,[rmax]
- sub ebx,[rmin]
- js .WIRandom_1
- inc ebx
- mov ecx,edx
- mul ebx
- mov eax,ecx
- mov ecx,edx
- mul ebx
- add eax,ecx
- adc edx,[rmin]
- mov eax,edx
- pop ebx
- ret
- .WIRandom_1:
- mov eax,80000000h
- pop ebx
- ret
- endp
- ;---------------------------------------------
- ; Инициализация генератора случайных чисел
- ; stdcall WRandomInit,seed
- ;---------------------------------------------
- proc WRandomInit seed:dword
- mov eax,[seed]
- xor ecx,ecx
- .WRandomInit_1:
- imul eax,2891336453
- inc eax
- mov [randbuf+ecx*4],eax
- inc ecx
- cmp ecx,KK*2
- JB .WRandomInit_1
- fld1
- fstp [randp1]
- mov [p1],0
- mov [p2],JJ*8
- stdcall WBRandom
- push edi
- mov edi,30
- .WRandomInit_2:
- stdcall WBRandom
- dec edi
- jnz .WRandomInit_2
- pop edi
- ret
- endp
- ;---------------------------------------------
- ; Вспомогательная процедура генератора
- ; В пользовательском не вызывается
- ;---------------------------------------------
- proc WBRandom
- push ebx
- mov ebx, [p1]
- mov ecx, [p2]
- mov edx, [randbuf+ebx]
- mov eax, [randbuf+ebx+4]
- rol edx, R1
- rol eax, R2
- add edx, [randbuf+ecx]
- add eax, [randbuf+ecx+4]
- mov [randbuf+ebx], eax
- mov [randbuf+ebx+4], edx
- sub ebx, 8
- jnc .WBRandom_1
- mov ebx, (KK-1)*8
- .WBRandom_1:
- sub ecx, 8
- jnc .WBRandom_2
- mov ecx, (KK-1)*8
- .WBRandom_2:
- mov [p1], ebx
- mov [p2], ecx
- pop ebx
- ret
- endp
Просмотров: 4182 | Комментариев: 7
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(12.12.2011 в 14:36):
Как зависит генерация от мощности компьютера? Не пиши ерунду.
Старк
(12.12.2011 в 14:34):
Этот генератор на мощном компьютере одно и тоже число выдавать не будет?
Fedor666
(02.06.2011 в 22:02):
Где, интересно знать, результаты тестов этого чуда? Ent? Deadhard :)
4RESTER
(27.10.2010 в 01:36):
Классический приличный RNG -- Mersenne Twister.
serega386
(20.09.2010 в 20:36):
proc WRandom
stdcall WBRandom
or edx, 80000000h
mov dword [randp1],eax
mov dword [randp1+4],edx
>>> fld1
>>> fld [randp1]
ret
endp
>>> для чего эти команды?
stdcall WBRandom
or edx, 80000000h
mov dword [randp1],eax
mov dword [randp1+4],edx
>>> fld1
>>> fld [randp1]
ret
endp
>>> для чего эти команды?
ManHunter
(17.05.2010 в 10:26):
Я его тестил на больших числах, там он конечно рулит.
Zummenix
(17.05.2010 в 09:41):
100 проходов, числа в диапазоне от 1 до 100:
62,30,63,53,66,41,67,11,61,4,85,28,65,73,10,83,4,6,86,32,43,25,62,54,3 6,64,60,69,97,79,43,13,56,68,64,93,23,14,94,28,72,60,8,65,52,7,62,53,4 6,17,53,83,24,45,13,65,48,60,71,44,27,70,39,9,22,24,24,56,80,93,32,55, 82,95,80,21,35,94,38,89,48,69,31,80,43,77,65,81,27,22,56,36,31,3,96,43 ,45,26,87,20
Очень даже неплохо, но некоторые числа повторяются, а некоторых вообще нет :)
62,30,63,53,66,41,67,11,61,4,85,28,65,73,10,83,4,6,86,32,43,25,62,54,3 6,64,60,69,97,79,43,13,56,68,64,93,23,14,94,28,72,60,8,65,52,7,62,53,4 6,17,53,83,24,45,13,65,48,60,71,44,27,70,39,9,22,24,24,56,80,93,32,55, 82,95,80,21,35,94,38,89,48,69,31,80,43,77,65,81,27,22,56,36,31,3,96,43 ,45,26,87,20
Очень даже неплохо, но некоторые числа повторяются, а некоторых вообще нет :)
Добавить комментарий
Заполните форму для добавления комментария
