Смекни!
smekni.com

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

2.3. Подсчёт контрольного кода четности

Для вычисления контрольного кода чётности будем использовать подсчёт битов в исходных элементах массива. С учётом ёмкости контрольного числа в 32 бита для массивов, размер которых не более 32 байта, используем битовое маскирование результирующего кода, а для массивов большего размера – подсчёт байтов, количество битов в которых чётно.

Блок-схема алгоритма имеет вид:

Из блок-схемы видно, что алгоритм подсчета контрольного кода четности использует два вложенных алгоритма: битового маскирования результата и подсчета количества байтов с четным количеством бит.

2.4. Битовое маскирование

Традиционно массивы в графическом виде представляются в виде последовательности элементов, упорядоченных слева направо, а двоичные числа – справа налево:

Такое представление затрудняет понимание общей природы массивов и двоичных чисел. Достаточно упорядочить элементы массива и биты двоичного числа в одном направлении и, возможно, ввести нумерацию элементов массива с 0, чтобы увидеть, что по сути двоичное число – это обычный массив, элементами которого являются биты:

С учётом этого факта несложно построить алгоритм формирования контрольного числа, в котором последовательно будут проверяться элементы массива и в зависимости от результата проверки соответствующие биты контрольного числа будут устанавливаться в 1 или 0. Текстовое описание такого алгоритма:

1. Обнулить контрольное число

2. Установить указатель на последний элемент массива

3. Проверить на четность очередной элемент массива

4. Если чётный, установить флаг переноса в 1. Иначе установить в 0.

5. Выполнить битовый сдвиг контрольного числа с учётом флага переноса на 1 разряд в сторону старших разрядов.

6. Если все элементы массива обработаны, закончить.

7. Иначе перейти к предыдущему элементу массива и продолжить с пункта 3

Графическое представление алгоритма в виде блок-схемы:

2.5. Подсчет в массиве байтов с четным количеством бит

Подсчёт количества байтов с чётным количеством бит реализовать достаточно просто:

Обнулить результат

Установить указатель на первый элемент массива

Проверить на чётность очередной элемент массива

Если чётный, добавить к результату 1

Если все элементы массива обработаны, закончить

Иначе перейти к предыдущему элементу массива и продолжить с пункта 3


Графическое представление алгоритма в виде блок-схемы:

2.6. Проверка элементов массива на чётность

Для проверки отдельных байтов массива на чётность удобно использовать команду test, которая вычисляет результат действия побитового логического «И» над приёмником и источником и устанавливает флаги SF, ZF и PF в соответствии с результатом, при этом результат не сохраняется. Если после выполнения команды test флаг PF будет установлен в 1, количество бит в байте чётно.

1. Вывод на экран текстовых сообщений

Наиболее простое решение – использовать для вывода текста функцию 9hDOS (прерывание INT21h), которая получает адрес строки для вывода через регистр dx, причем строка должна завершаться символом $.

2. Преобразование числа к строковому виду

В качестве основы используем реализацию алгоритма преобразования числа

в десятичное представление. [4, 201]

Суть используемого алгоритма заключается в выполнении следующих действий:

Разделить исходное число на 10.

Добавить к остатку ASCII-код нуля.

Записать полученную цифру в стек.

Увеличить счётчик цифр.

Если ещё есть что делить, продолжить с п.1

По количеству цифр: извлечь цифру из стека и дописать в конец результирующей строки.

Дописать в конец результирующей строки символ $.

Базовый алгоритм рассчитан на работу с 16-разрядными числами. Так как в разрабатываемой программе код чётности будет представлен в виде 32-разрядного числа, модифицируем исходный алгоритм для работы с двойными словами. Такая модификация выполняется достаточно просто заменой в исходном коде наименований регистров: ax на eax, bx на ebx, dx на edx.

3. Ввод числовых данных

С учётом того, что разрабатываемая программа является тестовой и не требует специфического управления клавиатурой, ввод с клавиатуры запрограммируем с помощью функций DOS.

Соответственно, алгоритм ввода числа в виде текстового описания будет выглядеть следующим образом:

Подготовить буфер ввода данных

Вызвать функцию DOS 0Ah для ввода с клавиатуры

Проверить количество введенных символов. Если = 0, ошибка

Выполнить проверку ввода десятичного числа


В целях обеспечения возможности повторного использования, а также для более простого понимания алгоритма в нём выделен отдельный подалгоритм проверки ввода десятичного числа.

4. Алгоритм проверки ввода десятичного числа

Алгоритм проверки ввода десятичного числа можно представить в виде текстового описания:

1) Проверить количество символов. Если больше 5, ошибка

2) Обнулить результат

3) Читать символ из буфера ввода

4) Если код символа меньше «0» или больше «9», ошибка

5) Получить промежуточный результат вычитанием кода символа «0»

6) Умножить на 10 результат

7) Если в ходе умножения получено переполнение, ошибка

8) Прибавить к результату промежуточный результат

9) Если обработаны не все символы, перейти к следующему символу. Переход к п.3

10) Если обработаны все символы, вернуть результат

Приложение

ПРИЛОЖЕНИЕ 1. ЛИСТИНГ ПРОГРАММЫ НА ЯЗЫКЕ ASSEBLER

. modelsmall; модель памяти

. stack 100h; сегмент стека

. data; сегмент данных

MAXDIGITSequ16; максимальное количество символов

; для ввода целого числа

BUFFERSIZEequMAXDIGITS + 2 + 1; объем буфера ввода

bufferdbBUFFERSIZEdup(?) ; буфер ввода

ARRAYSIZEequ4; количество элементов массива / 4

dataArraydb4*ARRAYSIZEdup(?) ; массив данных

changeValueNodb? ; номер элемента массива для изменения

changeValuedb? ; новое значение элемента массива

parityCodedd? ; код четности

; переменные для работы генератора случайных чисел

rand_add69621

rand_mdd7FFFFFFFh

seeddd-1

;

; Сообщения для вывода на экран

;

welcomeMsgdb"Welcome to array parity checker. ", 0Dh, 0Ah

db0Dh, 0Ah

db"This program generates array with random values and calculates its parity code. ", 0Dh, 0Ah

db"Then you can change any array value and program will check parity code. ", 0Dh, 0Ah

db"Enjoy! ", 0Dh, 0Ah

db0Dh, 0Ah

db0Dh, 0Ah, "$"

errorMsgdb"Parity check error. ", 0Dh, 0Ah, "$"

okMsgdb"Parity check ok. ", 0Dh, 0Ah, "$"

dataMsgdb"Array data: $"

codeMsgdb"Parity code: $"

numberMsgdb"Enter array item number to change (0. .15): $"

valueMsgdb"Enter new value (0. .255): $"

uncorrectMsgdb"Incorrect number. $"

writelndb0Dh, 0Ah, "$"

byeMsgdb"Bye! ", 0Dh, 0Ah, "$"

itemSeparatordb" $"

. code; сегмент кода

.386; программа для процессора 80386

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

; Главная программа

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

start: movax, @data

movds, ax; настройка регистров

moves, ax;

andsp, not 3; выравнивание границы стека

; во избежание ошибки доступа к памяти

movax, 0003h; видеорежим 3, очистка экрана и установка курсора

int10h

movdx, offset welcomeMsg; вывести приветствие

callshowString

callfillArray; заполнить массив случайными данными

movcx, ARRAYSIZE * 4; рассчитать контрольное число

; и записать в parityCode

movsi, offset dataArray

movdi, offset parityCode

callsaveParityCode

callshowArray; вывести значения элементов массива

moveax, parityCode

callshowParityCode

callinputValueNo; запросить у пользователя номер

; элемента массива для изменения

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

; элемента массива

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

callshowArray; вывести значения элементов массива

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

callshowParityCode

cmpparityCode, eax

jeparityCode_notChanged

parityCode_Changed:

movdx, offset errorMsg; сообщение об изменении кода четности

callshowString

jmpmain_exit

parityCode_notChanged:

movdx, offset okMsg; сообщение о неизменности кода четности

callshowString

main_exit:

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

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

movdx, offset byeMsg; до свидания

callshowString

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

movax, 4c00h; завершение выполнения программы

int21h

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

;

; Заполнить массив случайными данными.

;

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

;

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

;

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

;

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

; [ref] dataArray - массив данных для заполнения

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

;

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

fillArrayproc

pusheax

pushcx

pushedi

movedi, offset dataArray; указатель на массив данных

movcx, ARRAYSIZE; размер массива

fillArray_loop:

callrand; генерировать случайное число в eax

cld; направление записи - вперед

stosd; записать в очередной элемент массива

loopfillArray_loop

popedi

popcx

popeax

ret

fillArrayendp

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

; Генерация случайного числа.

;

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

;

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

; eax - случайное положительное 32-битное число (от 0 до 2^31 - 2)

;

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

; eax

;

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

; [in] rand_a – коэффициент a

; [in] rand_m – коэффициент m

; [ref] seed – последнее случайное число