Ассемблер 2

МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ ОТКРЫТЫЙ УНИВЕРСИТЕТ

ФАКУЛЬТЕТ ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ













ПОЯСНИТЕЛЬНАЯ ЗАПИСКА К КУРСОВОЙ РАБОТЕ

по дисциплине:

«Системное программирование»













Выполнил: Тябенков А.О.

студент IV курса МГОУ

Специальность: 200106

Шифр: 6041013/ с



Проверил: Юрагов Е.А.







2008


МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ ОТКРЫТЫЙ  УНИВЕРИТЕТ



Факультет информатики и радиоэлектроники

Кафедра: Информационная измерительная техника

Специальность: 200106





ЗАДАНИЕ





На курсовой проект  Тябенкова Антона Олеговича        Шифр: 6041013/с





1. Тема работы: 

 На языке ассемблера разработать алгоритм контроля, на циклический CRC-код, массива данных хранящегося в некоторой  области памяти. Код должен быть сохранен для последующей  периодической проверки массива данных. В случае несовпадения  на экран должно выводиться сообщение об искажении данных.

2. Содержание пояснительной записки:

Введение

1. Создание программы на ассемблере

2. Синтаксис ассемблера

3. Описание алгоритма

4. Описание программы

Заключение

Список литературы





3. Дата выдачи задания: 



4. Срок выполнения:



Задание выдал     _______________Юрагов Е.А.



Задание принял   _______________Тябенков А.О.

			
СОДЕРЖАНИЕ



	Введение	2

	1. Создание программы на ассемблере	6

	2. Синтаксис ассемблера	12

	3. Описание алгоритма	17

	4. Описание программы	19

	Приложение 1 Блок-схема алгоритма 	20

	Приложение 2 Листинг программы	21

	Заключение	26

	Список литературы	27


ВВЕДЕНИЕ



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

В то же время, внося в микропроцессор принципиальные изменения, разработчики были вынуждены постоянно иметь в виду необходимость обеспечения совместимости новых моделей со старыми, чтобы не отпугивать потенциального покупателя перспективой полной замены освоенного или разработанного им программного обеспечения. В результате современные микропроцессоры типа Pentium, обеспечивая такие возможности, как 32-битную адресацию почти неограниченных объемов памяти, многозадачный режим с одновременным выполнением нескольких программ, аппаратные средства защиты операционной системы и прикладных программ друг от друга, богатый набор дополнительных эффективных команд и способов адресации, в то же время могут работать (и часто работают) в режиме первых микропроцессоров типа 8086, используя всего лишь 1 мегабайт оперативной памяти, 16-разрядные операнды (т. е. числа в диапазоне до 216-1=65535) и ограниченный состав команд. Поскольку программирование на языке ассемблера напрямую затрагивает аппаратные возможности микропроцессора, прежде всего, следует выяснить, в какой степени программист может использовать новые возможности микропроцессоров в своих программах, и какие проблемы программной несовместимости могут при этом возникнуть.

Первые персональные компьютеры корпорации IBM, появившиеся в 1981 г. и получившие название IBM PC, использовали в качестве центрального вычислительного узла 16-разрядный микропроцессор с 8-разрядной внешней шиной Intel 8088. В дальнейшем в персональных компьютерах стал использоваться и другой вариант микропроцессора, 8086, который отличался от 8088 тем, что являлся полностью 16-разрядным. С тех пор его имя стало нарицательным, и в программах, использующих только возможности процессоров 8088 или 8086, говорят, что они работают в режиме 86-го процессора.

В 1983 г. корпорацией Intel был предложен микропроцессор 80286, в котором был реализован принципиально новый режим работы, получивший название защищенного. Однако процессор 80286 мог работать и в режиме 86-го процессора, который стали называть реальным.

В дальнейшем на смену процессору 80286 пришли модели 80386, i486 и, наконец, различные варианты процессора Pentium. Все они могут работать и в реальном, и в защищенном режимах. Хотя каждая следующая модель была значительно совершеннее предыдущей (в частности, почти на два порядка возросла скорость работы процессора, начиная с модели 80386 процессор стал 32-разрядным, а в процессорах Pentium реализован даже 64-разрядный обмен данными с системной шиной), однако с точки зрения программиста все эти процессоры весьма схожи. Основным их качеством является наличие двух режимов работы — реального и защищенного. Строго говоря, в современных процессорах реализован еще и третий режим — виртуального 86-го процессора, или V86, однако в плане использования языка ассемблера этот режим не отличается от обычного режима 86-го процессора, и в этой книге мы его касаться не будем.

Реальный и защищенный режимы прежде всего принципиально различаются способом обращения к оперативной памяти компьютера. Метод адресации памяти, используемый в реальном режиме, позволяет адресовать память лишь в пределах 1 Мбайт; в защищенном режиме используется другой механизм (из-за чего, в частности, эти режимы и оказались полностью несовместимыми), позволяющий обращаться к памяти объемом до 4 Гбайт. Другое важное отличие защищенного режима заключается в аппаратной поддержке многозадачности с аппаратной же (т.е. реализованной в самом микропроцессоре) защитой задач друг от друга.

Реальный и защищенный режимы имеют прямое отношение к работе операционной системы, установленной на компьютере.

В настоящее время на персональных компьютерах типа IBM PC используются в основном два класса операционных систем (оба — разработки корпорации Microsoft): однозадачная текстовая система MS-DOS и многозадачная графическая система Windows. Операционная система MS-DOS является системой реального режима; другими словами, она использует только средства процессора 8086, даже если она установлена на компьютере с процессором Pentium. Система Windows — это система защищенного режима; она значительно более полно использует возможности современных процессоров, в частности, многозадачность и расширенное адресное пространство. Разумеется, система Windows не могла бы работать с процессором 8086, так как в нем не был реализован защищенный режим.

Соответственно двум типам операционных систем, и все программное обеспечение персональных компьютеров подразделяется на два класса: программы, предназначенные для работы под управлением MS-DOS (их часто называют приложениями DOS) и программы, предназначенные для системы Windows (приложения Windows). Естественно, приложения. DOS могут работать только в реальном режиме, а приложения Windows - только в защищенном.

Таким образом, выражения «программирование в системе MS-DOS», «программирование в реальном режиме» и «программирование 86-го процессора» фактически являются синонимами. При этом следует подчеркнуть, что хотя процессор 8086, как микросхема, уже давно не используется, его архитектура и система команд целиком вошли в современные процессоры. Лишь относительно небольшое число команд современных процессоров специально предназначены для организации защищенного режима и распознаются процессором, только когда он работает в защищенном режиме. 

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

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


СОЗДАНИЕ ПРОГРАММЫ НА АССЕМБЛЕРЕ.



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

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

1.Этап постановки и формулировки задачи:

изучение предметной области и сбор материала в проблемно-ориентированном контексте;

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

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

определение структур входных и выходных данных;

формирование ограничений и допущений на исходные и выходные данные.

2.Этап проектирования:

формирование «ассемблерной» модели задачи;

выбор метода реализации задачи;

разработка алгоритма реализации задачи;

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

3. Этап кодирования:

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

программирование задачи;

комментирование  текста  программы  и  составление  предварительного описания программы.

4.   Этап отладки и тестирования:

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

обнаружение, локализация и устранение ошибок в программе, выявленных в тестах;

корректировка кода программы и ее описания.

5.   Этап эксплуатации и сопровождения:

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

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

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

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

К порядку применения и полноте выполнения перечисленных этапов нужно подходить разумно. Многое определяется особенностями конкретной задачи, ее назначением, объемом кода и обрабатываемых данных, другими характеристиками задачи. Некоторые из этих этапов могут либо выполняться одновременно с другими этапами, либо вовсе отсутствовать. 

Традиционно у существующих реализаций ассемблера нет интегрированной среды, подобной интегрированным средам Turbo Pascal, Turbo С или Visual C++. Поэтому для выполнения всех функций по вводу кода программы, ее трансляции, редактированию и отладке необходимо использовать отдельные служебные программы. Большая часть их входит в состав специализированных пакетов ассемблера.

На рисунке один приведена общая схема процесса разработки программы на ассемблере. На схеме выделено четыре шага процесса. На первом шаге, когда вводится код программы, можно использовать любой текстовый редактор. Основным требованием к нему является то, чтобы он не вставлял посторонних символов (спецсимволов редактировании). Файл должен иметь расширение . asm.




Рис. 1. «Процесс разработки программы на ассемблере».



Программы, реализующие остальные шаги схемы, входят в состав программного пакета ассемблера. После написания текста программы на ассемблере наступает следующий этап — трансляция программы. На этом шаге формируется объектный модуль, который включает в себя представление исходной программы в машинных кодах и некоторую другую информацию, необходимую для отладки и компоновки его с другими модулями. Традиционно на рынке ассемблеров для микропроцессоров фирмы Intel имеется два пакета: «Макроассемблер» MASM фирмы Microsoft и Turbo Assembler TASM фирмы Borland.

У этих пакетов много общего. Пакет макроассемблера фирмы Microsoft (MASM) получил свое название потому, что он позволял программисту задавать макроопределения (или макросы), представляющие собой именованные группы команд. Они обладали тем свойством, что их можно было вставлять в программу в любом месте, указав только имя группы в месте вставки. Пакет Turbo Assembler (TASM) интересен тем, что имеет два режима работы. Один из этих режимов, называемый MASM, поддерживает все основные возможности макроассемблера MASM. Другой режим, называемый IDEAL, предоставляет более удобный синтаксис написания программ, более эффективное использование памяти при трансляции программы и другие новшества, приближающие компилятор ассемблера к компиляторам языков высокого уровня.

В эти пакеты входят трансляторы, компоновщики, отладчики и другие утилиты для повышения эффективности процесса разработки программ на ассемблере. 

В данной курсовой работе для получения объектного модуля исходный файл подвергается трансляции при помощи программы tasm.exe из пакета TASM. 

После устранения ошибок можно приступать к следующему шагу — созданию исполняемого (загрузочного) модуля, или, как еще называют этот процесс, к компоновке программы. Главная цель этого шага — преобразовать код и данные в объектных файлах в их перемещаемое выполняемое отображение. Процесс создания исполняемого модуля разделяют на 2 шага — трансляцию и компоновку. Это сделано намеренно для того, чтобы можно было объединять вместе несколько модулей (написанных на одном или нескольких языках). Формат объектного файла позволяет, при определенных условиях, объединить несколько отдельно оттранслированных исходных модулей в один модуль. При этом в функции компоновщика входит разрешение внешних ссылок (ссылок на процедуры и переменные) в этих модулях. Результатом работы компоновщика является создание загрузочного файла с расширением ехе. После этого операционная система может загрузить такой файл  и выполнить его.

Устранение  синтаксических ошибок еще не гарантирует того, что программа будет хотя бы будет запускаться, не говоря уже о правильности работы. Поэтому обязательным этапом процесса разработки является отладка.

На этапе отладки, используя описание алгоритма, выполняется контроль правильности функционирования как отдельных участков кода, так и всей программы в целом. Но даже успешное окончание отладки еще не является гарантией того, что программа будет работать правильно со всеми возможными исходными данными. Поэтому нужно обязательно провести тестирование программы, то есть проверить ее работу на «пограничных» и заведомо некорректных исходных данных. Для этого составляются тесты. 

Специфика программ на ассемблере состоит в том, что они интенсивно работают с аппаратными ресурсами компьютера. Это обстоятельство заставляет программиста постоянно отслеживать содержимое определенных регистров и областей памяти. Естественно, что человеку трудно следить за этой информацией с большой степенью детализации. Поэтому для локализации логических ошибок в программах используют специальный тип программного обеспечения - программные отладчики.

Отладчики бывают двух типов:

интегрированные — отладчик реализован в виде интегрированной среды типа среды для языков Turbo Pascal, Quick С и т.д.;

автономные — отладчик представляет собой отдельную программу.

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


2. СИНТАКСИС АССЕМБЛЕРА



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

Предложения ассемблера формируются из лексем, представляющих собой синтаксически  неразделимые последовательности допустимых символов языка имеющие смысл для транслятора. Лексемами являются:

		идентификаторы — последовательности допустимых символов, использующиеся для обозначения таких объектов программы, как коды операций, имена переменных и названия меток. Правило записи идентификаторов заключается в следующем. Идентификатор может состоять из одного или нескольких символов. В качестве символов можно использовать буквы латинского алфавита, цифры и некоторые специальные знаки — _, ?, $, @. 

		цепочки символов — последовательности символов, заключенные в одинарные или двойные кавычки;

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

Практически каждое предложение содержит описание объекта, над которым или при помощи которого выполняется некоторое действие. Эти объекты называются операндами. Их можно определить так: операнды — это объекты (некоторые значения, регистры или ячейки памяти), на которые действуют инструкции или директивы, либо это объекты, которые определяют или уточняют действие инструкций или директив.

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

Рассмотрим классификацию операндов, поддерживаемых транслятором ассемблера.

Постоянные или непосредственные операнды — число, строка, имя или выражение, имеющие некоторое фиксированное значение. Имя не должно быть перемещаемым, то есть зависеть от адреса загрузки программы в память. 

Адресные операнды — задают физическое расположение операнда в памяти с помощью указания двух составляющих адреса: сегмента и смещений (рис. 2).







Рис. 2. «Синтаксис описания адресных операндов».



Перемещаемые операнды — любые символьные имена, представляющие некоторые адреса памяти. Эти адреса могут обозначать местоположение в памяти некоторой инструкции (если операнд — метка) или данных (если операнд — имя области памяти в сегменте данных). Перемещаемые операнды отличаются от адресных тем, что они не привязаны к конкретному адресу физической памяти. Сегментная составляющая адреса перемещаемого операнда неизвестна и будет определена после загрузки программы в память для выполнения. 

Считчик адреса — специфический вид операнда. Он обозначается знаком $. Специфика этого  операнда в том, что когда транслятор ассемблера встречает в  исходной программе этот символ, то он подставляет вместо него текущее значение  счетчика адреса. Значение счетчика адреса, или как его иногда называют  счетчика размещения, представляет собой смещение текущей машинной команды относительно начала сегмента кода. 

Базовый и индексный операнды. Этот тип операндов используется для реализации косвенной базовой, косвенной индексной адресации или их комбинаций и расширений. 

Операнды являются элементарными компонентами, из которых формируется часть машинной команды, обозначающая объекты, над которыми выполняется операция. В более общем случае операнды могут входить как составные части в более сложные образования, называемые выражениями. Выражения представляют собой комбинации операндов и операторов, рассматриваемые как единое целое. Результатом вычисления выражения может быть адрес некоторой ячейки памяти или некоторое константное (абсолютное) значение. В табл. 2.2 приведены поддерживаемые языком ассемблера операторы и перечислены их приоритеты. 

Арифметические операторы. К ним относятся унарные операторы «+» и «-», бинарные «+» и «-», операторы умножения «*», целочисленного деления «/», получения остатка от деления «mod». Эти операторы расположены на уровнях приоритета 6, 7, 8 в табл. 2.1.

Операторы сдвига выполняют сдвиг выражения на указанное количество разрядов.

Операторы сравнения (возвращают значение «истина» или «ложь») предназначены для формирования логических выражений (табл. 5.1). I Логическое значение «истина» соответствует цифровой единице, а «ложь» —  нулю.

Табл. 2.1.

Операторы сравнения

Оператор

Значение

eq

ИСТИНА, если выражение_1 равно выражение_2 

пе

ИСТИНА, если выражение_1 не равно выражение_2 

It

ИСТИНА, если выражение_1 меньше выражение_2 

le

ИСТИНА, если выражение_1 меньше или равно выражение_2 

gt

ИСТИНА, если выражение_1 больше выражение_2 

ge

ИСТИНА, если выражение_1 больше или равно выражение_2

eq

ИСТИНА, если выражение_1 равно выражение_2 

пе

ИСТИНА, если выражение_1 не равно выражение_2 



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

Индексный оператор [ ]. Скобки тоже являются оператором, и транслятор их наличие воспринимает, как указание сложить значение выражение_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.