Начало...
Рассмотрим работу функции для вещественных (дробных) чисел.
function Random3: extended;
const two2neg32 = 1/$100000000; // 2^-32
var z: int64;
begin
RandSeed:=RandSeed*$8088405 + 1;
z:=RandSeed;
If z<0 then
z:=z+$100000000;
Result:=z*two2neg32;
end;
Примечание 1. Допускается перегружать процедуры и функции с одинаковыми именами, дописав слово overload:
function Random1: extended; overload;
Примечание 2. Константа two2neg32 равна 0,00000000023283064365386962890625 (2 в степени -32).
Рассмотрим пример образования последовательности вещественных чисел в диапазоне от 0 до 1. Процедуру Randomize вызывать не будем (RandSeed = 0). Последовательность чисел будем вызывать с помощью функций Random3 и Random (для проверки).
procedure TForm1.Button2Click(Sender: TObject);
const rs = 0;
var i: integer;
a: real;
begin
Memo1.Clear;
RandSeed:=rs;
For i:=1 to 30 do
begin
a:=Random;
Memo1.Lines.Add(Format('%d число = %g, RandSeed = %d',[i,a,RandSeed]));
end;
Memo2.Clear;
RandSeed:=rs;
For i:=1 to 30 do
begin
a:=Random3;
Memo2.Lines.Add(Format('%d число = %g, RandSeed = %d',[i,a,RandSeed]));
end;
end;
Тексты в Memo1 и Memo2 будут выглядеть одинаково:
1 число = 2,3283064365387E-10, RandSeed = 1
2 число = 0,0313799395225942, RandSeed = 134775814
3 число = 0,861048467224464, RandSeed = -596792289
4 число = 0,202580965124071, RandSeed = 870078620
5 число = 0,272921267198399, RandSeed = 1172187917
6 число = 0,671654418576509, RandSeed = -1410233534
7 число = 0,318691271124408, RandSeed = 1368768587
8 число = 0,161795465275645, RandSeed = 694906232
9 число = 0,372238358715549, RandSeed = 1598751577
10 число = 0,425673767458647, RandSeed = 1828254910
11 число = 0,0820121595170349, RandSeed = 352239543
12 число = 0,474794064648449, RandSeed = 2039224980
13 число = 0,0705693301279098, RandSeed = 303092965
14 число = 0,84085443476215, RandSeed = -683524998
15 число = 0,0597242347430438, RandSeed = 256513635
16 число = 0,293296571820974, RandSeed = 1259699184
17 число = 0,917284708702937, RandSeed = -355259471
18 число = 0,367906478699297, RandSeed = 1580146294
19 число = 0,774664897238836, RandSeed = -967806897
20 число = 0,327925535850227, RandSeed = 1408429452
21 число = 0,697674974100664, RandSeed = -1298476099
22 число = 0,844170969445258, RandSeed = -669280590
23 число = 0,717982857255265, RandSeed = -1211254405
24 число = 0,306641304865479, RandSeed = 1317014376
25 число = 0,162625851342455, RandSeed = 698472713
26 число = 0,329496453981847, RandSeed = 1415176494
27 число = 0,46602045907639, RandSeed = 2001542631
28 число = 0,24665364716202, RandSeed = 1059369348
29 число = 0,825676416279748, RandSeed = -748714091
30 число = 0,279029483441263, RandSeed = 1198422506
Таким образом, при неоднократном вызове Random функция выдаст последовательность чисел: 2,3283064365387E-10, 0,0313799395225942, 0,861048467224464, 0,202580965124071, 0,272921267198399, 0,671654418576509, 0,318691271124408, 0,161795465275645, 0,372238358715549, 0,425673767458647, 0,0820121595170349, 0,474794064648449, 0,0705693301279098, 0,84085443476215, 0,0597242347430438, 0,293296571820974 и т.д.
Рассмотрим подробно образование случайных чисел. Вычисления проведем в таблице.
Число |
Код (команда) |
Значение z |
Значение RandSeed |
Значение Result |
Подробное вычисление |
Исходные данные: RandSeed = 0; постоянная two2neg32
= 0,00000000023283064365386962890625 = 2-32 |
1 |
RandSeed:=RandSeed*$8088405 + 1; |
0 |
1 |
0 |
RandSeed = RandSeed * $8088405 + 1 = 0 * 134775813 + 1 = 1 |
z:=RandSeed; |
1 |
1 |
0 |
z = RandSeed = 1 |
If z<0 then z:=z+$100000000; |
< не выполняется > |
Result:=z*two2neg32; |
1 |
1 |
2,3283064365387E-10 |
Result = z * two2neg32 = 1 * 2-32 = 2,3283064365387 * 10-10 |
Вывод: 1 число = 2,3283064365387E-10, RandSeed = 1 |
2 |
RandSeed:=RandSeed*$8088405 + 1; |
0 |
134775814 |
0 |
RandSeed = RandSeed * $8088405 + 1 = 1 * 134775813 + 1 = 134775814 |
z:=RandSeed; |
134775814 |
134775814 |
0 |
z = RandSeed = 134775814 |
If z<0 then z:=z+$100000000; |
< не выполняется > |
Result:=z*two2neg32; |
134775814 |
134775814 |
0,0313799395225942 |
Result = z * two2neg32 = 134775814 * 2-32 = 0,0313799395225942 |
Вывод: 2 число = 0,0313799395225942, RandSeed = 134775814 |
3 |
RandSeed:=RandSeed*$8088405 + 1; |
0 |
-596792289 |
0 |
RandSeed = RandSeed * $8088405 + 1 = 134775814 * 134775813 + 1 =
18164519904586783 ($408888DC6DAC1F) |
Примечание. Поскольку тип Integer принимает
значения -2147483648..2147483647, занимает 4 байта, то в памяти
компьютера произойдет переполнение: 18164519904586783 > 2147483647.
В этом случае, в переменную RandSeed запишется только 4 младших байта
($DC6DAC1F), а остальную часть ($408888) отбросит. Т.к. число $DC6DAC1F
= 3698175007 > 2147483647, в этом случае переменная RandSeed примет
отрицательное значение: -596792289. |
z:=RandSeed; |
-596792289 |
-596792289 |
0 |
z = RandSeed = -596792289 |
If z<0 then z:=z+$100000000; |
3698175007 |
-596792289 |
0 |
If -596792289<0 then z = -596792289 + 4294967296 = 3698175007 |
Примечание. Размер переменной z составляет 8 байт
(тип Int64), поэтому для корректной работы необходимо положительное
значение, добавив небольшое условие. |
Result:=z*two2neg32; |
3698175007 |
-596792289 |
0,861048467224464 |
Result = z * two2neg32 = 3698175007 * 2-32 = 0,861048467224464 |
Вывод: 3 число = 0,861048467224464, RandSeed = -596792289 |
4 |
RandSeed:=RandSeed*$8088405 + 1; |
0 |
870078620 |
0 |
RandSeed = RandSeed * $8088405 + 1 = -596792289 * 134775813 + 1 =
<для корректной работы -596792289 заменим на 3698175007> =
3698175007 * 134775813 + 1 = 498424543184705692
($6EAC27B33DC589C) |
z:=RandSeed; |
870078620 |
870078620 |
0 |
z = RandSeed = 870078620 |
If z<0 then z:=z+$100000000; |
< не выполняется > |
Result:=z*two2neg32; |
870078620 |
870078620 |
0,202580965124071 |
Result = z * two2neg32 = 870078620 * 2-32 = 0,202580965124071 |
Вывод: 4 число = 0,202580965124071, RandSeed = 870078620 |
5 |
RandSeed:=RandSeed*$8088405 + 1; |
0 |
1172187917 |
0 |
RandSeed = RandSeed * $8088405 + 1 = 870078620 * 134775813 + 1 =
117265553384418061
($1A09C6645DE2B0D) |
z:=RandSeed; |
1172187917 |
1172187917 |
0 |
z = RandSeed = 1172187917 |
If z<0 then z:=z+$100000000; |
< не выполняется > |
Result:=z*two2neg32; |
1172187917 |
1172187917 |
0,272921267198399 |
Result = z * two2neg32 = 1172187917 * 2-32 = 0,272921267198399 |
Вывод: 5 число = 0,272921267198399, RandSeed = 1172187917 |
Далее аналогичным образом рассчитываются следующие числа.
Рассмотрим следующую функцию, написанную на ассемблере.
function Random4: extended;
const two2neg32: double = 1/$100000000; // 2^-32
asm
IMUL EDX,RandSeed,$8088405
INC EDX
MOV RandSeed,EDX
FLD QWORD PTR two2neg32
PUSH $0
PUSH EDX
FILD QWORD PTR [ESP]
ADD ESP,$4
POP EDX
FMULP
FSTP TBYTE PTR Result
end;
Комментарии:
IMUL EDX,RandSeed,$8088405 - умножает RandSeed на $8088405 и записывает в регистр EDX;
INC EDX - увеличивает значение регистра EDX на единицу;
MOV RandSeed,EDX - присваивает переменной RandSeed значение регистра EDX;
FLD QWORD PTR two2neg32 - загружает 64-разрядное вещественное число two2neg32 в ST(0) (вершину стека сопроцессора);
PUSH $0 - размещает значение "0" в стеке, т.е. помещает значение в ячейку памяти, на которую указывает регистр ESP, после этого значение регистра ESP уменьшается на 4;
PUSH EDX - размещает значение регистра EDX в стеке;
FILD QWORD PTR [ESP] - загружает 64-разрядное целое число в регистр ST(0) (вершину стека сопроцессора) из области памяти по адресу ESP, при загрузке какого-либо значения в стек сопроцессора все значения стека сдвигаются, т.е. значение регистра ST(0) загрузит в ST(1), а наше новое значение загружается в ST(0);
ADD ESP,$4 - увеличивает значение регистра ESP на 4;
POP EDX - извлекает значение из стека, т.е. извлекает значение из ячейки памяти, на которую указывает регистр ESP, и сохраняет в регистре EDX, после этого увеличивает значение регистра ESP на 4;
FMULP - умножение значений регистра ST(0) сопроцессора на ST(1) и выталкивание из стека (значение в ST(1) будет Empty /нет данных/), результат записывается в ST(0);
FSTP TBYTE PTR Result - записывает 80-разрядное вещественное число из регистра ST(0) в переменную Result, при этом происходит выталкивание вершины из стека сопроцессора (ST(0) = Empty).
Рассмотрим пример образования последовательности вещественных чисел в диапазоне от 0 до 1. Процедуру Randomize вызывать не будем (RandSeed = 0). Последовательность чисел будем вызывать с помощью функций Random4 и Random (для проверки).
В процедуре TForm1.Button2Click в коде заменим функцию Random3(r) на Random4(r).
Тексты в Memo1 и Memo2 будут выглядеть одинаково:
1 число = 2,3283064365387E-10, RandSeed = 1
2 число = 0,0313799395225942, RandSeed = 134775814
3 число = 0,861048467224464, RandSeed = -596792289
4 число = 0,202580965124071, RandSeed = 870078620
5 число = 0,272921267198399, RandSeed = 1172187917
6 число = 0,671654418576509, RandSeed = -1410233534
7 число = 0,318691271124408, RandSeed = 1368768587
8 число = 0,161795465275645, RandSeed = 694906232
9 число = 0,372238358715549, RandSeed = 1598751577
10 число = 0,425673767458647, RandSeed = 1828254910
11 число = 0,0820121595170349, RandSeed = 352239543
12 число = 0,474794064648449, RandSeed = 2039224980
13 число = 0,0705693301279098, RandSeed = 303092965
14 число = 0,84085443476215, RandSeed = -683524998
15 число = 0,0597242347430438, RandSeed = 256513635
16 число = 0,293296571820974, RandSeed = 1259699184
17 число = 0,917284708702937, RandSeed = -355259471
18 число = 0,367906478699297, RandSeed = 1580146294
19 число = 0,774664897238836, RandSeed = -967806897
20 число = 0,327925535850227, RandSeed = 1408429452
21 число = 0,697674974100664, RandSeed = -1298476099
22 число = 0,844170969445258, RandSeed = -669280590
23 число = 0,717982857255265, RandSeed = -1211254405
24 число = 0,306641304865479, RandSeed = 1317014376
25 число = 0,162625851342455, RandSeed = 698472713
26 число = 0,329496453981847, RandSeed = 1415176494
27 число = 0,46602045907639, RandSeed = 2001542631
28 число = 0,24665364716202, RandSeed = 1059369348
29 число = 0,825676416279748, RandSeed = -748714091
30 число = 0,279029483441263, RandSeed = 1198422506
Таким образом, при неоднократном вызове Random функция выдаст последовательность чисел: 2,3283064365387E-10, 0,0313799395225942, 0,861048467224464, 0,202580965124071, 0,272921267198399, 0,671654418576509, 0,318691271124408, 0,161795465275645, 0,372238358715549, 0,425673767458647, 0,0820121595170349, 0,474794064648449, 0,0705693301279098, 0,84085443476215, 0,0597242347430438, 0,293296571820974 и т.д.
Рассмотрим подробно образование случайных чисел. Вычисления проведем в таблице.
Число |
Код (команда) |
Значение регистра EDX |
Значение регистра ESP |
Стек |
Сопроцессор |
Значение RandSeed |
Значение Result |
Подробное вычисление |
Исходные данные: RandSeed = 0; постоянная two2neg32
= 0,00000000023283064365386962890625 = 2-32 |
1 |
IMUL EDX,RandSeed,$8088405 |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = Empty |
0 |
0 |
EDX = RandSeed * $8088405 = 0 * 134775813 = 0 ($0) |
Примечание. В регистры будем записывать только
шестнадцатеричные значения, а в скобках - десятичные. |
INC EDX |
$00000001 (1) |
$0018F2C8 |
- |
ST0 = Empty |
0 |
0 |
EDX = EDX + 1 = 0 + 1 = 1 ($1) |
MOV RandSeed,EDX |
$00000001 (1) |
$0018F2C8 |
- |
ST0 = Empty |
$1 (1) |
0 |
RandSeed = EDX = 1 ($1) |
FLD QWORD PTR two2neg32 |
$00000001 (1) |
$0018F2C8 |
- |
ST0 = 2,3283064365387E-10
ST1 = Empty |
$1 (1) |
0 |
ST(0) = two2neg32 = 2-32 = 2,3283064365387 * 10-10 |
PUSH $0 |
$00000001 (1) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$1 (1) |
0 |
ESP = ESP - $4 = $18F2C8 - $4 = $18F2C4 [ESP] = [$18F2C4] = 0 ($0) |
PUSH EDX |
$00000001 (1) |
$0018F2C0 |
$0018F2C4: $00000000 (0)
$0018F2C0: $00000001 (1) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$1 (1) |
0 |
ESP = ESP - $4 = $18F2C4 - $4 = $18F2C0
[ESP] = [$18F2C0] = EDX = 1 ($1) |
FILD QWORD PTR [ESP] |
$00000001 (1) |
$0018F2C0 |
$0018F2C4: $00000000 (0) $0018F2C0: $00000001 (1) |
ST0 = 1
ST1 = 2,3283064365387E-10 ST2 = Empty |
$1 (1) |
0 |
ST(1) = ST(0) = 2,3283064365387 * 10-10
ST(0) = [ESP] = [$18F2C0] = 1 |
ADD ESP,$4 |
$00000001 (1) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 1 ST1 = 2,3283064365387E-10 ST2 = Empty |
$1 (1) |
0 |
ESP = ESP + $4 = $18F2C0 + $4 = $18F2C4 |
POP EDX |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 1 ST1 = 2,3283064365387E-10 ST2 = Empty |
$1 (1) |
0 |
EDX = [ESP] = [$18F2C0] = 0 ($0)
ESP = ESP + $4 = $18F2C4 + $4 = $18F2C8 |
FMULP |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$1 (1) |
0 |
ST(0) = ST(0) * ST(1) = 1 * 2,3283064365387 * 10-10 =
2,3283064365387 * 10-10 |
FSTP TBYTE PTR Result |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = Empty |
$1 (1) |
2,3283064365387E-10 |
Result = ST(0) = 2,3283064365387 * 10-10 |
Вывод: 1 число = 2,3283064365387E-10, RandSeed = 1 |
2 |
IMUL EDX,RandSeed,$8088405 |
$08088405 (134775813) |
$0018F2C8 |
- |
ST0 = Empty |
$1 (1) |
0 |
EDX = RandSeed * $8088405 = 1 * 134775813 = 134775813 ($8088405) |
INC EDX |
$08088406 (134775814) |
$0018F2C8 |
- |
ST0 = Empty |
$1 (1) |
0 |
EDX = EDX + 1 = 134775813 + 1 = 134775814 ($8088406) |
MOV RandSeed,EDX |
$08088406 (134775814) |
$0018F2C8 |
- |
ST0 = Empty |
$8088406 (134775814) |
0 |
RandSeed = EDX = 134775814 ($8088406) |
FLD QWORD PTR two2neg32 |
$08088406 (134775814) |
$0018F2C8 |
- |
ST0 = 2,3283064365387E-10
ST1 = Empty |
$8088406 (134775814) |
0 |
ST(0) = two2neg32 = 2-32 = 2,3283064365387 * 10-10 |
PUSH $0 |
$08088406 (134775814) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$8088406 (134775814) |
0 |
ESP = ESP - $4 = $18F2C8 - $4 = $18F2C4 [ESP] = [$18F2C4] = 0 ($0) |
PUSH EDX |
$08088406 (134775814) |
$0018F2C0 |
$0018F2C4: $00000000 (0)
$0018F2C0: $8088406 (134775814) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$8088406 (134775814) |
0 |
ESP = ESP - $4 = $18F2C4 - $4 = $18F2C0
[ESP] = [$18F2C0] = EDX = 134775814 ($8088406) |
FILD QWORD PTR [ESP] |
$08088406 (134775814) |
$0018F2C0 |
$0018F2C4: $00000000 (0) $0018F2C0: $8088406 (134775814) |
ST0 = 134775814
ST1 = 2,3283064365387E-10 ST2 = Empty |
$8088406 (134775814) |
0 |
ST(1) = ST(0) = 2,3283064365387 * 10-10
ST(0) = [ESP] = [$18F2C0] = 134775814 |
ADD ESP,$4 |
$08088406 (134775814) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 134775814 ST1 = 2,3283064365387E-10 ST2 = Empty |
$8088406 (134775814) |
0 |
ESP = ESP + $4 = $18F2C0 + $4 = $18F2C4 |
POP EDX |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 134775814 ST1 = 2,3283064365387E-10 ST2 = Empty |
$8088406 (134775814) |
0 |
EDX = [ESP] = [$18F2C0] = 0 ($0)
ESP = ESP + $4 = $18F2C4 + $4 = $18F2C8 |
FMULP |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 0,0313799395225942 ST1 = Empty |
$8088406 (134775814) |
0 |
ST(0) = ST(0) * ST(1) = 134775814 * 2,3283064365387 * 10-10 =
0,0313799395225942 |
FSTP TBYTE PTR Result |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = Empty |
$8088406 (134775814) |
0,0313799395225942 |
Result = ST(0) = 0,0313799395225942 |
Вывод: 2 число = 0,0313799395225942, RandSeed = 134775814 |
3 |
IMUL EDX,RandSeed,$8088405 |
$DC6DAC1E (3698175006) |
$0018F2C8 |
- |
ST0 = Empty |
$8088406 (134775814) |
0 |
EDX = RandSeed * $8088405 = 134775814 * 134775813 = 18164519904586782
($408888DC6DAC1E) |
Примечание. Старшее слово ($408888) нигде не
записывается (оно не учитывается). В регистр EDX записываются только
младшие разряды шестнадцатеричного числа. |
INC EDX |
$DC6DAC1F (3698175007) |
$0018F2C8 |
- |
ST0 = Empty |
$8088406 (134775814) |
0 |
EDX = EDX + 1 = 3698175006 + 1 = 3698175007 ($DC6DAC1F) |
MOV RandSeed,EDX |
$DC6DAC1F (3698175007) |
$0018F2C8 |
- |
ST0 = Empty |
$DC6DAC1F (-596792289) |
0 |
RandSeed = EDX = -596792289 ($DC6DAC1F) |
Примечание. Поскольку тип Integer принимает
значения -2147483648..2147483647, то число будет занимать 4 байта. Т.к.
число $DC6DAC1F = 3698175007 > 2147483647, в этом случае переменная
RandSeed примет отрицательное значение: -596792289. |
FLD QWORD PTR two2neg32 |
$DC6DAC1F (3698175007) |
$0018F2C8 |
- |
ST0 = 2,3283064365387E-10
ST1 = Empty |
$DC6DAC1F (-596792289) |
0 |
ST(0) = two2neg32 = 2-32 = 2,3283064365387 * 10-10 |
PUSH $0 |
$DC6DAC1F (3698175007) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$DC6DAC1F (-596792289) |
0 |
ESP = ESP - $4 = $18F2C8 - $4 = $18F2C4 [ESP] = [$18F2C4] = 0 ($0) |
PUSH EDX |
$DC6DAC1F (3698175007) |
$0018F2C0 |
$0018F2C4: $00000000 (0)
$0018F2C0: $DC6DAC1F (3698175007) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$DC6DAC1F (-596792289) |
0 |
ESP = ESP - $4 = $18F2C4 - $4 = $18F2C0
[ESP] = [$18F2C0] = EDX = 3698175007 ($DC6DAC1F) |
FILD QWORD PTR [ESP] |
$DC6DAC1F (3698175007) |
$0018F2C0 |
$0018F2C4: $00000000 (0) $0018F2C0: $DC6DAC1F (3698175007) |
ST0 = 3698175007
ST1 = 2,3283064365387E-10 ST2 = Empty |
$DC6DAC1F (-596792289) |
0 |
ST(1) = ST(0) = 2,3283064365387 * 10-10
ST(0) = [ESP] = [$18F2C0] = 3698175007 |
ADD ESP,$4 |
$DC6DAC1F (3698175007) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 3698175007 ST1 = 2,3283064365387E-10 ST2 = Empty |
$DC6DAC1F (-596792289) |
0 |
ESP = ESP + $4 = $18F2C0 + $4 = $18F2C4 |
POP EDX |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 3698175007 ST1 = 2,3283064365387E-10 ST2 = Empty |
$DC6DAC1F (-596792289) |
0 |
EDX = [ESP] = [$18F2C0] = 0 ($0)
ESP = ESP + $4 = $18F2C4 + $4 = $18F2C8 |
FMULP |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 0,861048467224464 ST1 = Empty |
$DC6DAC1F (-596792289) |
0 |
ST(0) = ST(0) * ST(1) = 3698175007 * 2,3283064365387 * 10-10 =
0,861048467224464 |
FSTP TBYTE PTR Result |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = Empty |
$DC6DAC1F (-596792289) |
0,861048467224464 |
Result = ST(0) = 0,861048467224464 |
Вывод: 3 число = 0,861048467224464, RandSeed = -596792289 |
4 |
IMUL EDX,RandSeed,$8088405 |
$33DC589B (870078619) |
$0018F2C8 |
- |
ST0 = Empty |
$DC6DAC1F (-596792289) |
0 |
EDX = RandSeed * $8088405 = -596792289 * 134775813 = <для
корректной работы -596792289 заменим на 3698175007> = 3698175007 *
134775813 = 498424543184705691
($6EAC27B33DC589B) |
INC EDX |
$33DC589C (870078620) |
$0018F2C8 |
- |
ST0 = Empty |
$DC6DAC1F (-596792289) |
0 |
EDX = EDX + 1 = 870078619 + 1 = 870078620 ($33DC589C) |
MOV RandSeed,EDX |
$33DC589C (870078620) |
$0018F2C8 |
- |
ST0 = Empty |
$33DC589C (870078620) |
0 |
RandSeed = EDX = 870078620 ($33DC589C) |
FLD QWORD PTR two2neg32 |
$33DC589C (870078620) |
$0018F2C8 |
- |
ST0 = 2,3283064365387E-10
ST1 = Empty |
$33DC589C (870078620) |
0 |
ST(0) = two2neg32 = 2-32 = 2,3283064365387 * 10-10 |
PUSH $0 |
$33DC589C (870078620) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$33DC589C (870078620) |
0 |
ESP = ESP - $4 = $18F2C8 - $4 = $18F2C4 [ESP] = [$18F2C4] = 0 ($0) |
PUSH EDX |
$33DC589C (870078620) |
$0018F2C0 |
$0018F2C4: $00000000 (0)
$0018F2C0: $33DC589C (870078620) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$33DC589C (870078620) |
0 |
ESP = ESP - $4 = $18F2C4 - $4 = $18F2C0
[ESP] = [$18F2C0] = EDX = 870078620 ($33DC589C) |
FILD QWORD PTR [ESP] |
$33DC589C (870078620) |
$0018F2C0 |
$0018F2C4: $00000000 (0) $0018F2C0: $33DC589C (870078620) |
ST0 = 870078620
ST1 = 2,3283064365387E-10 ST2 = Empty |
$33DC589C (870078620) |
0 |
ST(1) = ST(0) = 2,3283064365387 * 10-10
ST(0) = [ESP] = [$18F2C0] = 870078620 |
ADD ESP,$4 |
$33DC589C (870078620) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 870078620 ST1 = 2,3283064365387E-10 ST2 = Empty |
$33DC589C (870078620) |
0 |
ESP = ESP + $4 = $18F2C0 + $4 = $18F2C4 |
POP EDX |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 870078620 ST1 = 2,3283064365387E-10 ST2 = Empty |
$33DC589C (870078620) |
0 |
EDX = [ESP] = [$18F2C0] = 0 ($0)
ESP = ESP + $4 = $18F2C4 + $4 = $18F2C8 |
FMULP |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 0,202580965124071 ST1 = Empty |
$33DC589C (870078620) |
0 |
ST(0) = ST(0) * ST(1) = 870078620 * 2,3283064365387 * 10-10 =
0,202580965124071 |
FSTP TBYTE PTR Result |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = Empty |
$33DC589C (870078620) |
0,202580965124071 |
Result = ST(0) = 0,202580965124071 |
Вывод: 4 число = 0,202580965124071, RandSeed = 870078620 |
5 |
IMUL EDX,RandSeed,$8088405 |
$45DE2B0C (1172187916) |
$0018F2C8 |
- |
ST0 = Empty |
$33DC589C (870078620) |
0 |
EDX = RandSeed * $8088405 = 870078620 * 134775813 = 117265553384418060
($1A09C6645DE2B0C) |
INC EDX |
$45DE2B0D (1172187917) |
$0018F2C8 |
- |
ST0 = Empty |
$33DC589C (870078620) |
0 |
EDX = EDX + 1 = 1172187916 + 1 = 1172187917 ($45DE2B0D) |
MOV RandSeed,EDX |
$45DE2B0D (1172187917) |
$0018F2C8 |
- |
ST0 = Empty |
$45DE2B0D (1172187917) |
0 |
RandSeed = EDX = 1172187917 ($45DE2B0D) |
FLD QWORD PTR two2neg32 |
$45DE2B0D (1172187917) |
$0018F2C8 |
- |
ST0 = 2,3283064365387E-10
ST1 = Empty |
$45DE2B0D (1172187917) |
0 |
ST(0) = two2neg32 = 2-32 = 2,3283064365387 * 10-10 |
PUSH $0 |
$45DE2B0D (1172187917) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$45DE2B0D (1172187917) |
0 |
ESP = ESP - $4 = $18F2C8 - $4 = $18F2C4 [ESP] = [$18F2C4] = 0 ($0) |
PUSH EDX |
$45DE2B0D (1172187917) |
$0018F2C0 |
$0018F2C4: $00000000 (0)
$0018F2C0: $45DE2B0D (1172187917) |
ST0 = 2,3283064365387E-10 ST1 = Empty |
$45DE2B0D (1172187917) |
0 |
ESP = ESP - $4 = $18F2C4 - $4 = $18F2C0
[ESP] = [$18F2C0] = EDX = 1172187917 ($45DE2B0D) |
FILD QWORD PTR [ESP] |
$45DE2B0D (1172187917) |
$0018F2C0 |
$0018F2C4: $00000000 (0) $0018F2C0: $45DE2B0D (1172187917) |
ST0 = 1172187917
ST1 = 2,3283064365387E-10 ST2 = Empty |
$45DE2B0D (1172187917) |
0 |
ST(1) = ST(0) = 2,3283064365387 * 10-10
ST(0) = [ESP] = [$18F2C0] = 1172187917 |
ADD ESP,$4 |
$45DE2B0D (1172187917) |
$0018F2C4 |
$0018F2C4: $00000000 (0) |
ST0 = 1172187917 ST1 = 2,3283064365387E-10 ST2 = Empty |
$45DE2B0D (1172187917) |
0 |
ESP = ESP + $4 = $18F2C0 + $4 = $18F2C4 |
POP EDX |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 1172187917 ST1 = 2,3283064365387E-10 ST2 = Empty |
$45DE2B0D (1172187917) |
0 |
EDX = [ESP] = [$18F2C0] = 0 ($0)
ESP = ESP + $4 = $18F2C4 + $4 = $18F2C8 |
FMULP |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = 0,272921267198399 ST1 = Empty |
$45DE2B0D (1172187917) |
0 |
ST(0) = ST(0) * ST(1) = 1172187917 * 2,3283064365387 * 10-10 =
0,272921267198399 |
FSTP TBYTE PTR Result |
$00000000 (0) |
$0018F2C8 |
- |
ST0 = Empty |
$45DE2B0D (1172187917) |
0,272921267198399 |
Result = ST(0) = 0,272921267198399 |
Вывод: 5 число = 0,272921267198399, RandSeed = 1172187917 |
Далее аналогичным образом рассчитываются следующие числа.
Примечание 1. Здесь дополнительно используется значение регистра ESP - это указатель вершины стека. В регистре ESP хранится адрес последней добавленной записи.
Примечание 2. Строки "ADD ESP,$4" и "POP EDX" можно заменить одной строкой "ADD ESP,$8". Это означает, что команда ADD увеличит значение регистра ESP сразу на 8, а в регистре EDX останется старое значение.
|