Смекни!
smekni.com

Микропроцессор i8086/i8088 (стр. 5 из 6)

;

; Примечание:

; Используется алгоритм, описанный в [Зубков С.В.] на стр.238.

; Линейный конгруэнтный генератор описывается формулой:

;

; I [j + 1] = (a * I [j] + c) mod m

;

; При правильно выбранных числах a и c эта последовательность возвращает

; все числа от нуля до m - 1 псевдослучайным образом и ее периодичность

; сказывается только на последовательностях порядка m.

; Классический стандартный генератор Льюиса, Гудмана и Миллера

; использует a = 16807 (7^5) при m = 2^31 - 1.

; Генераторы Парка и Миллера используют a = 48271 и a = 69621

; при том же m.

; Используем последний вариант.

; Значения a и m задаются в глобальных переменных rand_a и rand_m.

; - ---------------------------------------------------------------------------------------

randproc

pushedx

moveax, dword ptr seed; считать последнее случайное число

testeax, eax; проверить его

jsfetch_seed; если не - 1, функция еще ни разу не вызывалась

; и надо создать начальное значение

randomize:

muldword ptr rand_a; умножить на число a

divdword ptr rand_m; взять остаток от деления на 2^31 - 1

moveax, edx

movdword ptr seed, eax; сохранить для следующих вызовов

popedx

ret

fetch_seed:

pushds

push0040h

popds

moveax, dword ptr ds: 006Ch; считать двойное слово из области данных BIOS

; по адресу 0040: 006C - текущее число тактов таймера

popds

jmpshortrandomize

randendp

; - ----------------------------------------------------------------------------------------

; Рассчитать контрольное число элементов массива и сохранить в переменной.

;

; Параметры:

; cx - размер массива

; ds: si - указатель на начало массива

; es: di - указатель на переменную-получатель

;

; Возвращаемое значение: нет

;

; Модификация регистров: нет

; - -----------------------------------------------------------------------------------------

saveParityCodeproc

pusheax

callgetParityCode; рассчитать контрольное число

mov [di], eax; сохранить результат

popeax

ret

saveParityCodeendp

; - ----------------------------------------------------------------------------------------

; Рассчитать контрольное число четности элементов массива.

; Если размер массива больше 32 байт, контрольное число

; рассчитывается методом суммирования - см. getParitySum

; Если размер массива не более 32 байт, контрольное число

; рассчитывается методом битовых масок - см. getParityBits

;

; Параметры:

; cx - размер массива

; ds: si - указатель на начало массива

;

; Возвращаемое значение:

; eax - 32-битное контрольное число

;

; Модификация регистров:

; eax

; - ----------------------------------------------------------------------------------------

getParityCodeproc

cmpcx, 32

jagetParityCode_sum

callgetParityBits

ret

getParityCode_sum:

callgetParitySum

ret

getParityCodeendp

; - -----------------------------------------------------------------------------------------

; Рассчитать контрольное число четности элементов массива методом битовых масок.

; Используется для массивов размером не более 32 байт.

; Для каждого байта определяется количество битов. Если оно четное, соответствующий

; бит контрольного числа устанавливается в 1, если нечетное - в 0.

; Нулевому байту массива соответствует нулевой бит контрольного числа и т.д.

;

; Параметры:

; cx - размер массива

; ds: si - указатель на начало массива

;

; Возвращаемое значение:

; eax - 32-битное контрольное число

;

; Модификация регистров:

; eax

; - ----------------------------------------------------------------------------------------

getParityBitsproc

pushebx

pushcx

pushsi

xorebx, ebx; обнулить результат

std; направление чтения - назад

addsi, cx; установить указатель на последний элемент массива

decsi

getParityBits_loop:

lodsb; прочитать байт данных в al

testal, al; проверить четность

jpgetParityBits_parity; если четность, перейти к установке флага cf

clc; сброс флага cf

jmpshort getParityBits_shift; перейти к формированию результата

getParityBits_parity:

stc; установить флаг cf

getParityBits_shift:

rclebx, 1; сдвиг влево на 1 бит с учетом флага cf

loopgetParityBits_loop

moveax, ebx; записать результат в eax

popsi

popcx

popebx

ret

getParityBitsendp

; - -----------------------------------------------------------------------------------------

; Рассчитать контрольное число четности элементов массива суммированием.

; Используется для массивов размером более 32 байт.

; Для каждого байта определяется количество битов. Если оно четное,

; контрольное число увеличиваем на 1.

;

; Параметры:

; cx - размер массива

; ds: si - указатель на начало массива

;

; Возвращаемое значение:

; eax - 32-битное контрольное число

;

; Модификация регистров:

; eax

;

; - ----------------------------------------------------------------------------------------

getParitySumproc

pushebx

pushcx

pushsi

xorebx, ebx; обнулить результат

cld; направление чтения - вперед

getParitySum_loop:

lodsb; прочитать байт данных в al

testal, al; проверить четность

jnpgetParitySum_next; если не четность, продолжить

incebx; увеличить результат на 1

getParitySum_next:

loopgetParitySum_loop

moveax, ebx; записать результат в eax

popsi

popcx

popebx

ret

getParitySumendp

; - -----------------------------------------------------------------------------------------

; Вывод на экран элементов массива.

;

; Параметры: нет

;

; Возвращаемое значение: нет

;

; Модификация регистров: нет

;

; Глобальные переменные:

; [in] dataMsg – сообщение

; [in] dataArray – массив данных

; [ref] buffer – буфер преобразования числа в строку

; [in] itemSeparator – разделитель элементов массива

; [in] ARRAYSIZE - размер массива

; - ----------------------------------------------------------------------------------------

showArrayproc

pusheax

pushcx

pushdx

pushsi

pushdi

movdx, offset dataMsg; сообщение

callshowString

xoreax, eax; обнулить аккумулятор

movsi, offsetdataArray; читать данные из массива данных

movdi, offsetbuffer

movcx, ARRAYSIZE * 4; размер массива, байт

showArray_loop:

cld; направление чтения - вперед

lodsb; прочитать байт данных в al

callint2dec; преобразовать в строку

movdx, offset buffer

callshowString; вывести на экран

movdx, offset itemSeparator

callshowString; вывести пробел

loopshowArray_loop

callwriteLine; перевод строки

popdi

popsi

popdx

popcx

popeax

ret

showArrayendp

; - ---------------------------------------------------------------------------------------

; Вывод на экран контрольного кода четности.

;

; Параметры:

; eax - контрольное число

;

; Возвращаемое значение: нет

;

; Модификация регистров: нет

;

; Глобальные переменные:

; [in] codeMsg – сообщение

; [ref] buffer – буфер преобразования числа в строку

; - -----------------------------------------------------------------------------------------

showParityCodeproc

pushdx

pushdi

movdx, offsetcodeMsg; сообщение

callshowString

movdi, offset buffer

callint2dec; преобразовать в строку

movdx, di

callshowString; вывести на экран

callwriteLine; перевод строки

popdi

popdx

ret

showParityCodeendp

; - ----------------------------------------------------------------------------------------

; Запросить у пользователя номер элемента массива для изменения.

;

; Параметры: нет

;

; Возвращаемое значение: нет

;

; Модификация регистров: нет

;

; Глобальные переменные:

; [in] ARRAYSIZE - размер массива

; [in] numberMsg – запрос на ввод номера элемента массива

; [in] uncorrectMsg – сообщение об ошибке

; [out] changeValueNo – результат ввода

; - ----------------------------------------------------------------------------------------

inputValueNoproc

pushbx

pushcx

pushdx

pushsi

pushdi

movbx, ARRAYSIZE * 4 - 1; максимально допустимое значение

movcl, 2; максимально допустимое количество символов

movdx, offset numberMsg; запрос на ввод номера элемента массива

movsi, offset uncorrectMsg; сообщение об ошибке

movdi, offset changeValueNo; запомнить результат ввода в changeValueNo

callinputNumber

popdi

popsi

popdx

popcx

popbx

ret

inputValueNoendp

; - -----------------------------------------------------------------------------------------

; Запросить у пользователя новое значение элемента массива.

;

; Параметры: нет

;

; Возвращаемое значение: нет

;

; Модификация регистров: нет

;

; Глобальные переменные:

; [in] valueMsg - запрос на ввод нового значения элемента массива

; [in] uncorrectMsg – сообщение об ошибке

; [out] changeValue – результат ввода

; - -----------------------------------------------------------------------------------------

inputValueproc

pushbx

pushcx

pushdx

pushsi

pushdi

movbx, 255; максимально допустимое значение

movcl, 3; максимально допустимое количество символов

movdx, offset valueMsg; запрос на ввод нового значения элемента массива

movsi, offset uncorrectMsg; сообщение об ошибке

movdi, offset changeValue; запомнить результат ввода в changeValue

callinputNumber

popdi

popsi

popdx

popcx

popbx

ret

inputValueendp

; - -----------------------------------------------------------------------------------------

; Изменить значение элемента массива.

;

; Параметры: нет

;

; Возвращаемое значение: нет

;

; Модификация регистров: нет

;

; Глобальные переменные:

; [ref] dataArray – массив данных

; [in] changeValueNo – номер элемента массива для изменения

; [in] changeValue – новое значение элемента массива

; - -----------------------------------------------------------------------------------------

changeItemproc

pushax

pushbx

pushsi

movbx, offset dataArray

xorax, ax

moval, changeValueNo

movsi, ax

moval, changeValue

mov [bx + si], al

popsi

popbx

popax

ret

changeItemendp

; - ----------------------------------------------------------------------------------------

; Запрос у пользователя числа.

; Вводятся беззнаковые целые числа в диапазоне 0. .65535.

;

; Параметры:

; bx - максимально допустимое значение

; cl - максимально допустимое количество символов

; dx - указатель на строку-приглашение для ввода

; si - указатель на сообщение об ошибке

; di - указатель на байтовую переменную-получатель

;

; Возвращаемое значение: нет

;

; Модификация регистров: нет

;

; Глобальные переменные:

; [ref] buffer – буфер преобразования строки в число

; - -----------------------------------------------------------------------------------------

inputNumberproc

pushax

pushdi

inputNumber_input:

callshowString; вывод строки-приглашения для ввода

movdi, offset buffer; указатель на буфер ввода

calldo_inputNumber

callwriteLine; перевод строки

jncinputNumber_exit; если нет ошибки ввода, выход

inputNumber_error:

pushdx

movdx, si; сообщение об ошибке

callshowString

popdx

jmpshort inputNumber_input

inputNumber_exit:

popdi

mov [di], al; запомнить результат ввода в переменной-получателе

popax

ret

inputNumberendp

; - -----------------------------------------------------------------------------------------

; Ввод числа.

; Вводятся беззнаковые целые числа в диапазоне 0. .65535.

;

; Параметры:

; bx - максимально допустимое значение

; cl - максимально допустимое количество символов

; es: di - указатель на буфер ввода

; первый байт буфера резервируется для записи максимально допустимого количества символов