Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как сделать случайный выбор? на MASM 
:(
    Опции темы
ЭтоопятьИрина
  Дата 9.9.2006, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 19.8.2006

Репутация: нет
Всего: нет



Подскажите под MASM примерчик, пожалуйста:
Как можно осуществить случайный выбор процедуры
 (В делфи это randomize)
примерно так:

a1 proc
...
a1 enmdp

a2 proc
...
a2 endp

a3 proc
...
a3 endp

start:

call случайный выбор из a1 .. a3
invoke Exitprocess, 0
Спасибо, Ирина.
PM MAIL   Вверх
Damarus
Дата 9.9.2006, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 671
Регистрация: 6.5.2006

Репутация: нет
Всего: 29



Цитата(ЭтоопятьИрина @  9.9.2006,  13:08 Найти цитируемый пост)
Как можно осуществить случайный выбор процедуры (В делфи это randomize)

В Delphi randomize инициализирует генератор случайных чисел.

PM MAIL ICQ Jabber   Вверх
sgi1981
Дата 9.9.2006, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 16.3.2006

Репутация: 2
Всего: 10



Тебе надо искать готовый или написать собственный генератор псевдослучайных чисел в виде функции. Причем такой, которая в качестве одного параметра принимает максимально возможное псевдослучайное число, а минимально возможное - 0.
Составить массив адресов случайно вызываемых подпрограмм, занести туда в элементы адреса точек входа в коды подпрограмм. Вызывать функцию генер. псевдослучайные числа с параметром {колич. элементов массива адресов - 1}.

Причем дополнительно необходимо инициализировать генератор чисел и лучше всего значением от таймера компьютера или еще лучше от системных часов.


--------------------
Тело в нашем пространстве - есть часть пространства, в которой пространство обладает дисторсией относительно внешнего пространства.
PM MAIL   Вверх
ЭтоопятьИрина
Дата 9.9.2006, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 19.8.2006

Репутация: нет
Всего: нет



блин...

Добавлено @ 19:54 
А почему не ноль а -1 ?
Чтобы не вылезти за границы массива?
PM MAIL   Вверх
Damarus
Дата 9.9.2006, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 671
Регистрация: 6.5.2006

Репутация: нет
Всего: 29



Цитата(ЭтоопятьИрина @  9.9.2006,  20:52 Найти цитируемый пост)
А почему не ноль а -1 ?Чтобы не вылезти за границы массива?

Да.
PM MAIL ICQ Jabber   Вверх
ЭтоопятьИрина
  Дата 10.9.2006, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 19.8.2006

Репутация: нет
Всего: нет



Блин, вот рабочий код где-то откопала.
Но куда мне вставить 
else   ?
Не могу вообще тут понять...

Кто-нибудь - добавте тут хотя бы основные комментарии,
чтобы прояснить, что тут такое. и как его модернизировать мне?
Я могу пока ещё только только с АПИ... Чистый асм для меня тяжело даётся...
Помогите...

 .386
        .model flat,stdcall
        option casemap:none
        include \masm32\include\windows.inc
        include \masm32\include\user32.inc
        include \masm32\include\kernel32.inc
        includelib \masm32\lib\user32.lib
        includelib \masm32\lib\kernel32.lib
.data
random_seed     dd ?
res             dd 0
sFmt            db '%u',0DH,0AH,0
sBuf            db 10 dup(0)


.code

Random proc dwBase:dword
push    ebx        
mov     eax,dwBase        
xor     ebx,ebx        
imul    edx,random_seed,08088405h        
inc     edx        
mov     random_seed,edx        
mul     edx        
mov     eax,edx        
pop     ebx        
ret
Random endp

Randomize proc        
invoke  GetTickCount
mov     random_seed,eax        
ret
Randomize endp


start:
invoke  Randomize
invoke  Random,56 
mov     res,EAX
invoke wsprintf,ADDR sBuf,ADDR sFmt,res ; или можно юзать макросы dwtoa,str$,etc
invoke MessageBox,0,ADDR sBuf,0,0
invoke  ExitProcess,0
end start


PM MAIL   Вверх
sgi1981
Дата 10.9.2006, 03:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 16.3.2006

Репутация: 2
Всего: 10



Код

.386
;используются инструкции моделей процессоров начиная с 80386
        .model flat,stdcall
;код и данные будут в одном сегменте памяти (плоская модель памяти)
;перед вызовом процедуры последовательность записи параметров в сегмент стека идет 
;СПРАВА НАЛЕВО в порядке указания их в команде вызова процедуры и вызываемая процедура 
;чистит за собой стек
        option casemap:none
;не создавать файл карты для модуля при компиляции модуля
;далее указываются подключаемые файлы, содержащие данные о строковых названиях
;импортируемых функций из библиотек ОС и строковых названиях соответствующих библиотек ОС
        include \masm32\include\windows.inc
        include \masm32\include\user32.inc
        include \masm32\include\kernel32.inc
        includelib \masm32\lib\user32.lib
        includelib \masm32\lib\kernel32.lib
.data
;начало описания данных
;здесь описываются метки ячеек памяти
random_seed     dd ?
res             dd 0
sFmt            db '%u',0DH,0AH,0
sBuf            db 10 dup(0) ;массив в памяти из десяти элементов по одному байту каждый


.code
;начало описания кода
;описание кода подпрограммы Random
;эта подпрограмма - генератор псевдослучайных чисел
Random proc dwBase:dword
;подпрограмма использует один входной параметр занимающий 4 байта, который перед вызовом
;подпрограммы записывается в сегмент стека
push    ebx;сохраним в стеке ebx, так как значение этого регистра изменяется в подпрограмме
;(в конце подпрограммы мы его опять восстановим)
mov     eax,dwBase;заносим исходный параметр в eax
xor     ebx,ebx; обнулить ebx
imul    edx,random_seed,08088405h; умножить random_seed на 08088405h и результат сохранить в edx
;знаки операндов учитываются
inc     edx;увеличить edx на 1
mov     random_seed,edx; записать edx в random_seed, 
;и таким образом обновить временное значение переменной используемой Random
mul     edx; умножить edx на eax и результат сохранить в паре регистров edx:eax 
;(старшая часть результата будет в edx) 
;пояснения:
;в регистре edx было получено целочисленное значение занимающее 4 байта
;если умножается целочисленное значение без знака, занимающее 4 байта 
;(32 бита в двоичной системе счисления) (его диапазон от 0 до 4294967296)
;на другое целочисленное значение занимающее 4 байта такого же диапазона,
;то мы получим целочисленное значение без учета знака, которое всегда займет не более 8 байт
;но 64 бита не помещаются ни в один 32 битный регистр общего назначения,
;поэтому разработчики архитектуры команд микропроцессора решили помещать
;результат в пару 32-битных регистров и выбрали пару edx:eax
;После умножения в нашем случае в регистре edx значение не превысит исходного значения в eax
;Почему ?
;Значение в edx после умножения эквивалентно тому значению, которое получилось бы в результате
;целочисленного деления результата умножения на {2 в 32 степени} без учета знака, 
;но так как второй сомножитель всегда меньше {2 в 32 степени}, то после деления результата
; на {2 в 32 степени} мы всегда бы получили значение не большее чем первый сомножитель
;напомню, что результат умножения мы в действительности не делим на {2 в 32 степени}
;просто значение в старшей половине 64-разрядного результата получается таковым
;таким образом 
mov     eax,edx; старшую часть результата поместить в регистр eax в качестве результата 
;выполнения подпрограммы
;в регистре eax подпрограммы обычно возвращают результат, если он не превышает 4 байт
pop     ebx; восстанавливаем значение ebx из стека
ret; инструкция выхода из подпрограммы
Random endp; endp сообщает компилятору о окончании описания подпрограммы

Randomize proc        
;подпрограмма инициализации генератора псевдослучайных чисел значением от таймера
invoke  GetTickCount; вызов системной подпрограммы (эта подпрограмма принадлежит ОС)
;которая возвращает количество тиков с момента старта WINDOWS
mov     random_seed,eax; инициализация генератора псевдослучайных чисел полученным значением
;числа тиков
ret
Randomize endp


start: ;с этой метки начинается выполнение нашей программы
;о том, с какой метки должно начинаться выполнение программы указывается в директиве end
invoke  Randomize;вызываем свою подпрограмму инициализации генератора псевдослучайных чисел
invoke  Random,56;вызываем свою подпрограмму-генератор псевдослучайного числа
;в зависимости от значения входного параметра будет зависеть дальнейшая последовательность
;псевдослучайных чисел
mov     res,EAX;полученное число в res
invoke wsprintf,ADDR sBuf,ADDR sFmt,res ; или можно юзать макросы dwtoa,str$,etc
;выводим результат в заданном формате
invoke MessageBox,0,ADDR sBuf,0,0;выводим сообщение на экран в окне
invoke  ExitProcess,0; завершение работы программы
end start; директива end указывает компилятору, что выполнение программы должно начинаться
;с метки start



Это сообщение отредактировал(а) sgi1981 - 10.9.2006, 03:08


--------------------
Тело в нашем пространстве - есть часть пространства, в которой пространство обладает дисторсией относительно внешнего пространства.
PM MAIL   Вверх
ЭтоопятьИрина
Дата 10.9.2006, 04:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 19.8.2006

Репутация: нет
Всего: нет



Спасибо, дорогой Сквай. ты уж очень подробно изложил...

Кое-что я и сама знаю - например
 
end start: это я знаю...   :-)

Вообще здорово ты всё это знаешь - молодец.
 Можно мне к тебе если что за советом обращаться лично?
PM MAIL   Вверх
sgi1981
Дата 10.9.2006, 07:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 16.3.2006

Репутация: 2
Всего: 10



Цитата(ЭтоопятьИрина @ 10.9.2006,  04:58)
Спасибо, дорогой Сквай. 


Всегда рад.
Цитата

Вообще здорово ты всё это знаешь - молодец.
Можно мне к тебе если что за советом обращаться лично?

Да. 
Меня звать Сахаров Григорий Иванович.
E-mail [email protected]
ICQ 194-333-217
Сайт http://sgi.bigtruck-canada.ca/

С удовольствием...

Это сообщение отредактировал(а) sgi1981 - 10.9.2006, 07:12


--------------------
Тело в нашем пространстве - есть часть пространства, в которой пространство обладает дисторсией относительно внешнего пространства.
PM MAIL   Вверх
dumb
Дата 11.9.2006, 03:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 7
Всего: 158



Цитата(sgi1981 @  10.9.2006,  03:07 Найти цитируемый пост)
        option casemap:none
;не создавать файл карты для модуля при компиляции модуля

эта чувствительность к регистру в символах...
PM MAIL   Вверх
mur
Дата 11.9.2006, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 11.9.2006

Репутация: нет
Всего: нет



Код который ты нашла изрядно захламлён в нём ebx зачем-то сохраняется, обнуляется и ... не используется

А лучше так (один из вариантов):

Код

; Макро для генерации ЦЕЛОГО псевдослучайного числа в диапазоне от 0 до (Max_Rand-1)
; Помещает в переменную [RND_num] целое псевдослучайное число в диапазоне 0..4294967295
; И возвращает в регистре EAX число в диапазоне 0..(Max_Rand - 1)
Rand MACRO Max_Rand
   ; [RND_num] = [RND_num] * 214013 + 2531011 - переполнение dword игнорировать!
   imul    EDX, [RND_num], 214013    ; EDX = [RND_num] * 214013
   add    EDX, 2531011    ; числа 214013, 2531011 могут быть другие, но не любые
   mov    [RND_num], EDX
   ; Обрезка случайного числа до попадания в диапазон:
      mov EAX, Max_Rand
      mul EDX                   ; EDX:EAX = EDX*EAX
      mov EAX, EDX    ; поместить в EAX обрезанное значение ( < Max_Rand)
ENDM 
 
;--------------------------------------------------------------------------------------- 
; Для того, чтобы случайным образом вызывать одну из процедур создаёшь таблицу адресов:
.data
Table_Function    dd offset a1, offset a2, offset a3
        dd offset a4, offset a5    ; и т.д. 
.data? 
  RND_num    dd ?    ; а это случайное число в диапазоне 0..4294967295
.code
; ... 
; это RANDOMIZE (можно не оформлять как подпрограмму)
invoke GetTickCount    ; Делаешь RND_num по настоящему случайным 
mov [RND_num], EAX    ; (достаточно один раз в начале программы): 
; ... 
; ... 
; А это собственно то что ты просила в первом вопросе 
; случайный выбор одной из функций 
; (можешь поместить это в цикл или обработчик события): 
  Rand 5 ; потому что в примере 5 функций! 
  call dword ptr [offset Table_Function + EAX * 4] ; <- А это вызов твоей функции ;) 
; случайный номер функции (в регистре EAX) умножить на 4 байта (размер элемента таблицы DWORD) 
; к нему прибавляется адрес таблицы: offset Table_Function 
; и call - вызов подпрограммы адрес которой dword ptr [...] находится в случайно выбранной ячейке таблицы. 
 
; Все !!! Просто и красиво, только следи, чтобы Max_Rand не было больше количества функций,
; а то программа будет слетать из-за вызова несуществующей proc. 
 
a1 proc    ; ----- Блок случайно вызываемых подпрограмм ----- 
; ... 
 ret    ; и не забывай перед endp ставить ret !!! 
a1 endp    ; endp означает только конец текста подпрограммы 
    ; а ret - собственно команда её завершения !!! 
a2 proc 
;... 
 ret 
a2 endp 
;..... 
 

 
 
 
 

Это сообщение отредактировал(а) mur - 12.9.2006, 07:55
PM MAIL   Вверх
sgi1981
Дата 12.9.2006, 00:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 16.3.2006

Репутация: 2
Всего: 10



Цитата
 div EBX        ; EDX:EAX / EBX 

to mur:
Не буду спорить, насколько корреляция меньше будет у псевдослучайных чисел в 
вашем случае, но инструкция div ebx выполняться может в среднем за 15 тактов АЛУ. Избегать div там где это возможно.


--------------------
Тело в нашем пространстве - есть часть пространства, в которой пространство обладает дисторсией относительно внешнего пространства.
PM MAIL   Вверх
mur
Дата 12.9.2006, 07:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 11.9.2006

Репутация: нет
Всего: нет



На счёт div согласен, внёс поправку !!!

А на счёт корелляции:
Цитата

числа 214013, 2531011 могут быть другие, но не любые

у Вас рассмотрен другой частный случай 08088405h и 1

По хорошему корелляцию нужно каждый раз тестировать, но приятно, что на одном движке
можно строить целую кучу разных генераторов!

PM MAIL   Вверх
ЭтоопятьИрина
Дата 12.9.2006, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 19.8.2006

Репутация: нет
Всего: нет



Спасибо, Сквай, за помощь.
Написала тебе личное письмо.
PM MAIL   Вверх
mur
Дата 13.9.2006, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 11.9.2006

Репутация: нет
Всего: нет



Ответы на многие вопросы найдёшь в книге Зубкова, в частности раздел 5.7.1 про генераторы случайных чисел
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Asm для начинающих"
MAKCim
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой КОД.
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, MAKCim.

 
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Asm для начинающих | Следующая тема »


 




[ Время генерации скрипта: 0.0863 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.