Логические операторы выполняют над выражениями побитовые операции. Выражения должны быть абсолютными, то есть такими, численное значение которых может быть вычислено транслятором.
Индексный оператор [ ]. Скобки тоже являются оператором, и транслятор их наличие воспринимает, как указание сложить значение выражение_1 за этими скобками с выражение_2, заключенным в скобки.
Оператор переопределения типа ptr применяется для переопределения или уточнения имя типа метки или переменной, определяемых выражением. Тип может принимать одно из следующих значений: byte, word, dword, qword, tbyte, noar, far. Оператор ptr позволяет непосредственно в команде переопределить тип и выполнить команду.
Оператор переопределения сегмента : (двоеточие) заставляет вычислять физический адрес относительно конкретно задаваемой сегментной составляющей: «имя сегментного регистра», «имя сегмента» из соответствующей директивы SEGMENT или «имя группы».
Оператор именования типа структуры . (точка) также заставляет транслятор производить определенные вычисления
Оператор получения сегментной составляющей адреса выражения seg возвращает физический адрес сегмента для выражения, в качестве которого могут выступать метка, переменная, имя сегмента, имя группы или некоторое символическое имя.
Оператор получения смещения выражения offset позволяет получить значения смещения выражения в байтах относительно начала того сегмента, в котором выражение определено.
3. ОПИСАНИЕ АЛГОРИТМА
Алгоритм реализует вычисление CRC8 делением заданного массива данных на образующий полином x8+x5+x4+1. Деление выполнено последовательным вычитанием по модулю 2 полинома из исходной последовательности.
Для этого организован цикл по словам исходной последовательности и цикл по разрядного сдвига внутри слова. Поскольку удобнее просматривать массив в порядке увеличения адреса (от младшего к старшему), процедура реализует зеркальный алгоритм.
Подробнее о том как выполняется деление при вычислении CRC смотри в прилагаемых источниках.
Для процедуры вычисления исходные данные передаются через регистры. Сегментный регистр ES должен содержать сегмент в котором расположен массив, регистр DX – смещение начала массива внутри сегмента, BX – длина массива. Результат накапливается в аккумуляторе AL.
Перед началом вычислений инициируем AX значением FFFFh. В регистр CX заносим длину массива и умножаем её на 8. Таким образом этот регистр хранит количество разрядов в массиве и используется как счётчик циклов командой loop. Дополнять исходную последовательность (проверяемый массив) нулями нет необходимости, т.к. количество разрядов кратно степени образующего многочлена.
Смещение переносим в регистр DI.
В BX заносим первое слово массива.
Проверяем младший разряд BX. Если он равен нулю – выполняем сдвиг слова на один разряд вправо, если нет – выполняем сложение с образующим многочленом по модулю 2, а затем выполняем сдвиг.
Сдвиг по разрядам выполняется следующим образом. В DX хранится количество сдвигов оставшееся до конца слова (удобнее подсчитывать не количество выполненных сдвигов, а от количества разрядов в слове до 0). Если в DX – 0, то нужно в DX записать 8, а в BX загрузить следующее слово массива, иначе – просто сдвигаем BX вправо на разряд и уменьшаем DX на 1.
Повторяем суммирование.
После окончания процедуры аккумулятор AX содержит вычисленное для массива значение CRC8.
Для сохранения результата его переносим в переменную result.
Для проверки целостности массива нужно повторить вычисление контрольной суммы и сравнить со значением в result.
Блок-схема алгоритма приведена в приложении 1.
4. ОПИСАНИЕ ПРОГРАММЫ
Алгоритм определения CRC реализован в процедуре CalcCRC. Перед вызовом этой процедуры необходимо в регистры записать начальные данные - сегментный регистр ES должен содержать сегмент в котором расположен массив, регистр DX – смещение начала массива внутри сегмента, BX – длина массива.
Программа выполняет следующие операции по выбору пользователя: вычисление CRC массива и запись результата в переменную, проверка целостности массива – повторное вычисление CRC и сравнение вычисленного значения с записанным, искажение массива – обратимое изменение одного бита проверочного массива.
Для вычисления CRC, вызывается процедура CalcCRC, а результат выполнения сохраняется в переменной result.
При проверке целостности, вызывается процедура CalcCRC, а результат выполнения сравнивается с сохранённым в переменной result. В случае несовпадения, выводится сообщение об ошибке. При совпадении значений (целостность данных не нарушена) сообщение не выводится и пользователь возвращается в главное меню.
Искажение массива используется для тестирования программы и демонстрации работы.
Для тестирования в программе предусмотрен проверочный массив данных длиной 32 байта. При искажении, инвертируется младший бит первого слова массива.
ПРИЛОЖЕНИЕ 1
Блок-схема алгоритма
ПРИЛОЖЕНИЕ 2
MODEL SMALL
;*****************************************************************************
; Сегмент стека
;*****************************************************************************
_Stack SEGMENT WORD 'STACK'
DB 200h DUP (?)
_Stack ENDS
;*****************************************************************************
; Сегмент тестового массива
;*****************************************************************************
DataSeg SEGMENT WORD 'DATA'
TestTab DB 32 DUP ( \
00h, 01h, 02h, 03h, 04h, 05h, 06h, 07h, \
08h, 09h, 0Ah, 0Bh, 0Ch, 0Dh, 0Eh, 0Fh, \
00h, 01h, 02h, 03h, 04h, 05h, 06h, 07h, \
08h, 09h, 0Ah, 0Bh, 0Ch, 0Dh, 0Eh, 0Fh \
)
DataSeg ENDS
;*****************************************************************************
; Сегмент переменных
;*****************************************************************************
_Data SEGMENT WORD 'DATA'
;*****************************************************************************
FSelMsg DB 13,10,'Выберите действие:',13,10, \
13,10,'1-Определить CRC',13,10, \
'2-Проверить массив',13,10, \
'3-Исказить массив',13,10, \
'4-Выход',13,10, \
'$'
ByeStr DB 13,10,'Для продолжения нажмите любую клавишу.$'
ErrorString DB 13,10,'Ошибка ввода',13,10,'$'
ErrorResult DB 13,10,'Данные искажены. CRC8 нарушена.',13,10,'$'
;*****************************************************************************
BegSeg DW (?) ;Сегмент проверочного массива
BegOffs DW (?) ;Начало проверочного массива
Result DW (?) ;Результат вычисления
FuncNum DB (?) ;Выбранная операция
_Data ENDS
;*****************************************************************************
; Сегмент программы
;*****************************************************************************
.CODE
;*****************************************************************************
call cls ;Очистка экрана
call SetDATSeg ;Загрузка адреса сегмента переменных
call SetArrSeg ;Установка указателя сегмента массива
;Главное меню
Mnu: call SelectFunction ;Выбор операции
call cls ;Очистка экрана
mov AL,FuncNum
;*******************************
Mnu1: cmp AL,1 ;Определение чётности
jne Mnu2
;Установка параметров
mov DX,OFFSET TestTab ;Смещение начала массива
mov BX,30 ;Размер проверяемого блока данных
;call TestOdd
call CalcCRC
mov Result,AX ;Сохранение результата
;*******************************
Mnu2: cmp AL,2 ;Определить чётность и сравнить с пред.
jne Mnu3
mov DX,OFFSET TestTab ;Смещение начала массива
mov BX,30 ;Размер блока данных
call CalcCRC
cmp Result,AX
je Mnu2End
;Результат не совпал. Данные искажены. Выдать сообщение об ошибке
mov DX,OFFSET ErrorResult
mov AH,9h
int 21h ;Вывод сообщения об ошибке
mov DX,OFFSET ByeStr ;Вывод приглашения
mov AH,9h
int 21h
mov AH,0Ch
mov AL,01h
int 21h ;Ожидание нажатия любой клавиши
Mnu2End:
call cls
jmp Mnu
;*******************************
Mnu3: cmp AL,3 ;Искажение масива (первый байт)
jne Mnu4
mov DI,OFFSET TestTab
mov AX,ES:[DI]
xor AX,1 ;Инвертируем младший бит
mov ES:[DI],AX
;*******************************
Mnu4: cmp AL,4 ;Выход из программы
jne Mnu
;*******************************
jmp Exit
;Завершение программы
;Exit:
;Приостанов перед выходом
mov DX,OFFSET ByeStr ;?Нажмите клавишу??
mov AH,9h
int 21h
mov AH,0Ch
mov AL,01h
int 21h
Exit: ;Выход
mov AH,4Ch
int 21h
;*****************************************************************************
;Печать новой строки
NewStr:
mov AH,02h
mov DL,0Dh
int 21h
mov DL,0Ah
int 21h
ret
;*****************************************************************************
include cls.prc
;*****************************************************************************
;Главное меню
SelectFunction:
;1.1.Вывод строки меню
mov DX,OFFSET FSelMsg
mov AH,9h
int 21h
;1.2.Выбор функции
mov FuncNum,0
call input10 ;Считываем номер пункта меню
mov FuncNum,AL ;Сохраняем номер выбранной функции
ExitSF: ret
;*****************************************************************************
;Подпрограмма ввода числа
input10:
push BX ;Сохраняем регистры
push DX
push CX
mov DX,0 ;Обнуляем регистр хранения результата
InputChar:
clc
mov AH,0Ch
mov AL,1
int 21h ;Считываем символ с эхом
cmp AL,13d
je ExitI10 ;Если его код 13 ? конец ввода
cmp AL,'0'
jb ErrInput ;Если код меньше кода символа 0 ошибка ввода
cmp AL,'9'
jg ErrInput ;Если код больше кода символа 9 ошибка ввода
clc
sub AX,30h ;Получаем из кода символа число
mov CX,0
mov CL,AL
mov AX,DX
mov BX,10
mul BX ;Умножаем на 10 уже накопленный результат
add AX,CX ;Прибавляем считанное число
mov DX,AX ;Сохраняем результат
jmp InputChar
ErrInput:
Stc ;В случае ошибки ввода устанавливаем флаг
ExitI10:
mov AX,DX ;Переносим результат в регистр возврата
pop CX
pop DX
pop BX ;Восстанавливаем регистры
ret
;*****************************************************************************
;Установка указателя на сегмент переменных
SetDATSeg:
push AX
mov AX,_Data
mov DS,AX
pop AX
ret
;*****************************************************************************
;Установка указателя на проверочный массив
SetArrSeg proc
push AX
mov AX,DataSeg
mov ES,AX
pop AX
ret
SetArrSeg endp
;****************************************************************************
; Процедура вычисления CRC16
;ES - сегмент массива
;DX - адрес начала массива
;BX - длина блока данных
;AX - результат вычислений
;****************************************************************************
CalcCRC proc
push CX ;\
push BX ;- сохранение регистров
push DI ;/
push DX
mov DI,DX ;Загрузка индекса начала массива
mov DX,8
mov CX,BX ;Установка счётчика цикла
shl CX,1 ;\
shl CX,1 ;- CX=CX*8
shl CX,1 ;/
mov AX,65535 ;Очистка регистра результата
mov BX,ES:[DI]
CRNext: loop CRNextTest ;Цикл по словам массива
pop DX
pop DI ;\
pop BX ;-восстановление регистров
pop CX ;/
ret
CRNextTest:
push AX
mov AX,BX
and AX,1b
jz Shift
pop AX
xor AL,31h
push AX
Shift: mov AX,DX
jz NewWord
shr BX,1
dec DX
jmp EndShift
NewWord:
mov DX,8
inc DI
mov BX,ES:[DI]
EndShift:
pop AX
jmp CRNext
CalcCRC endp
;*****************************************************************************
END
;*****************************************************************************
ЗАКЛЮЧЕНИЕ
Ассемблер является символическим аналогом машинного языка. По этой причине программа, написанная на ассемблере, должна отражать все особенности архитектуры микропроцессора: организацию памяти, способы адресации операндов, правила использования регистров и т. д. Из-за необходимости учета подобных особенностей ассемблер уникален для каждого типа микропроцессоров.
В данной курсовой работе рассмотрены основные этапы программирования на ассемблере, реализован алгоритм выполнения поставленной задачи, а также выполнена трансляция кода в исполняемый файл.
СПИСОК ЛИТЕРАТУРЫ:
Финогенов К.Г. Основы языка Ассемблера. – М.: Радио и связь,2000.
Юров В. Assembler. Специальный справочник. – СПб.: Питер, 2001.
Юров В. Assembler. Практикум. – СПб.: Питер, 2001.
Юров В., Хорошенко В. Assembler – Учебный курс.- СПб.: Питер, 2000.
Do'stlaringiz bilan baham: |