
Генератор xoshiro128 на Ассемблере
Семейство xoshiro (xoroshiro) - это высокоскоростные и очень эффективные алгоритмы генерации псевдослучайных чисел общего назначения с хорошим распределением. Свое название генераторы получили от используемых в них операций XOR/Shift/Rotate. Разные варианты генераторов используют для рабочего буфера разные объемы памяти, а также реализованы как в 64-битной, так и в 32-битной версии. У меня тут будет 32-битный вариант xoshiro128 с периодом 2128.На всякий случай сразу уточню, что если в тексте встречается термин "случайное число", то имеется в виду "псевдослучайное число". У любого алгоритма генерации все равно есть зависимость и период, пусть даже очень большой, а создавать истинно случайные числа они не в состоянии.
Переходим к программированию. Как можно догадаться из суффикса названия, для работы генератора потребуется 128 бит, то есть 4 DWORD'а.
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; Данные для генератора случайных чисел
- s rd 4
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; Инициализация генератора случайных чисел
- ; stdcall long_jump,seed
- ;---------------------------------------------
- proc long_jump seed:DWORD
- locals
- s0 dd ?
- s1 dd ?
- s2 dd ?
- s3 dd ?
- endl
- pusha
- ; Начальное "засеивание" генератора
- mov edi,s
- mov eax,[seed]
- rol eax,1
- xor eax,0x1C580662
- stosd
- rol eax,3
- add eax,0x0B6F099F
- stosd
- rol eax,5
- xor eax,0xB523952E
- stosd
- rol eax,7
- sub eax,0xCCF5A0EF
- stosd
- ; Холостая прокрутка генератора для инициализации
- lea edi,[s0]
- push edi
- xor eax,eax
- stosd
- stosd
- stosd
- stosd
- xor ebx,ebx
- .loc_for_1:
- xor ecx,ecx
- .loc_for_2:
- mov eax,[.lj+ebx*4]
- and eax,1
- shl eax,cl
- jz @f
- mov esi,s
- lodsd
- xor [s0],eax
- lodsd
- xor [s1],eax
- lodsd
- xor [s2],eax
- lodsd
- xor [s3],eax
- @@:
- stdcall next
- inc ecx
- cmp ecx,32
- jb .loc_for_2
- inc ebx
- cmp ebx,4
- jb .loc_for_1
- pop esi
- mov edi,s
- movsd
- movsd
- movsd
- movsd
- popa
- ret
- .lj: dd 0xB523952E
- dd 0x0B6F099F
- dd 0xCCF5A0EF
- dd 0x1C580662
- endp
Функции генерации также представлены в трех вариантах - xoshiro128+, xoshiro128++ и xoshiro128**. Версии с "+" самые скоростные, но при этом имеют незначительную статистическую уязвимость, связанную со слабыми младшими битами. Поэтому рекомендуется использовать только старшие биты ее результата или же использовать "плюсовой" xoshiro128 для генерации вещественных чисел. Впрочем, это относится исключительно к каким-нибудь чувствительным решениям, где даже минимальные просчеты недопустимы. Для подавляющего большинства прикладных задач это никакого значения не имеет.
Самая первая версия алгоритма - xoshiro128+, количеством "плюсов" обозначено количество операций сложения, используемых при генерации.
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; Получить случайное число xoshiro128+
- ; stdcall next
- ; на выходе EAX - случайное число
- ;---------------------------------------------
- proc next
- pusha
- mov ecx,[s+3*4]
- add ecx,[s+0*4]
- mov ebx,[s+1*4]
- shl ebx,9
- mov eax,[s+0*4]
- xor [s+2*4],eax
- mov eax,[s+1*4]
- xor [s+3*4],eax
- mov eax,[s+2*4]
- xor [s+1*4],eax
- mov eax,[s+3*4]
- xor [s+0*4],eax
- xor [s+2*4],ebx
- mov eax,[s+3*4]
- mov ebx,eax
- shl eax,11
- shr ebx,(32-11)
- or eax,ebx
- mov [s+3*4],eax
- mov [esp+28],ecx
- popa
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; Получить случайное число xoshiro128++
- ; stdcall next
- ; на выходе EAX - случайное число
- ;---------------------------------------------
- proc next
- pusha
- mov eax,[s+3*4]
- add eax,[s+0*4]
- mov ebx,eax
- shl eax,7
- shr ebx,(32-7)
- or eax,ebx
- add eax,[s+0*4]
- mov ecx,eax
- mov ebx,[s+1*4]
- shl ebx,9
- mov eax,[s+0*4]
- xor [s+2*4],eax
- mov eax,[s+1*4]
- xor [s+3*4],eax
- mov eax,[s+2*4]
- xor [s+1*4],eax
- mov eax,[s+3*4]
- xor [s+0*4],eax
- xor [s+2*4],ebx
- mov eax,[s+3*4]
- mov ebx,eax
- shl eax,11
- shr ebx,(32-11)
- or eax,ebx
- mov [s+3*4],eax
- mov [esp+28],ecx
- popa
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; Получить случайное число xoshiro128**
- ; stdcall next
- ; на выходе EAX - случайное число
- ;---------------------------------------------
- proc next
- pusha
- xor edx,edx
- mov eax,[s+1*4]
- mov ecx,5
- mul ecx
- mov ebx,eax
- shl eax,7
- shr ebx,(32-7)
- or eax,ebx
- xor edx,edx
- mov ecx,9
- mul ecx
- mov ecx,eax
- mov ebx,[s+1*4]
- shl ebx,9
- mov eax,[s+0*4]
- xor [s+2*4],eax
- mov eax,[s+1*4]
- xor [s+3*4],eax
- mov eax,[s+2*4]
- xor [s+1*4],eax
- mov eax,[s+3*4]
- xor [s+0*4],eax
- xor [s+2*4],ebx
- mov eax,[s+3*4]
- mov ebx,eax
- shl eax,11
- shr ebx,(32-11)
- or eax,ebx
- mov [s+3*4],eax
- mov [esp+28],ecx
- popa
- ret
- endp
Просмотров: 1216 | Комментариев: 3
Метки: Assembler, генератор ПСЧ

Внимание! Статья опубликована больше года назад, информация могла устареть!

Добавить комментарий
Заполните форму для добавления комментария
