;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
; ГЕНЕРАТОР СЛУЧАЙНОГО ЧИСЛА 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				; Возврат из подпрограммы
