Автор: Пользователь скрыл имя, 25 Января 2012 в 10:10, курсовая работа
В курсовой работе в соответствии с заданием на проектирование решается задача на языке ассемблера для CPU i8086, в которой требуется вычислить значение логической формулы F=(X7&X6&X1) V (X6&X4&X2X1&X0 ) V (X7&X6&X3&X1) логическими переменными которой являются значения массива из 8 байт, и размещающей результат в оперативной памяти.
Описание пошаговой реализации алгоритма решения задачи в виде последовательности арифметических, логических и других действий, которые необходимо проделать для реализации принятого метода решения. Реализация задачи предполагает создание исходного, объектного и загрузочного модулей, а также подробное описание каждого действия по написанию программы.
Введение 4
1 Постановка задачи 6
2 Анализ задачи 8
2.1 Определение входной и выходной информации 8
2.2 Выбор модели памяти 8
2.3 Выбор режимов адресации 9
2.4 Разработка блок-схемы программы 12
3 Реализация 13
3.1 Описание этапов создания программы 13
3.1.1 Описание исходного модуля 16
3.1.2 Трансляция программы 18
3.2 Характеристика полученного файла листинга 20
3.3 Характеристика полученного загрузочного модуля 22
3.4 Анализ команд программы 22
3.5 Анализ команд jmp, jl, jg и loop 24
3.6 Анализ дампа памяти (сегменты данных, кода и стека) 27
4 Тестирование и отладка программы 29
4.1 Отладка программы 29
4.2 Тестирование программы 29
Заключение 33
Литература 34
Приложение А 35
Приложение Б 36
Приложение В 38
Приложение Г 39
В командах перехода непосредственно рассчитывать или определять смещение или сам адрес перехода программисту нет необходимости, программа ассемблера сделает это автоматически и, при необходимости, выдаст предупреждающее сообщение, если это сделать невозможно по тем или иным причинам. При написании программ целесообразно использовать метки, определяющие точку перехода и в тексте команд перехода использовать имена этих меток.
LOOP
<метка_перехода> – повторить цикл.
Работа команды заключается в выполнении
следующих действий: декремента регистра
cx и сравнения регистра cx с нулем. Если
cx > 0, то управление передается на метку
перехода, если cx = 0, то управление передается
на следующую после loop команду программы.
При загрузке программ в оперативную память DOS (дисковая операционная система) инициализирует как минимум три сегментных регистра:
Кодовый сегмент (CS) должен обязательно описываться в программе, все остальные сегменты могут отсутствовать. В этом случае DOS при загрузке программы в оперативную память инициирует регистры DS и ES значением адреса префикса программного сегмента PSP (Program Segment Prefics) – специальной области оперативной памяти размером 256 (100h) байт. PSP может использоваться в программе для определения имен файлов и параметров из командной строки, введенной при запуске программы на выполнение, объема доступной памяти, переменных окружения системы и т.д. Регистр SS при этом инициализируется значением сегмента, находящегося сразу за PSP, т.е. первого сегмента программы.
Обращение к памяти осуществляется исключительно посредством сегментов – логических образований, накладываемых на любые участки физического адресного пространства. Начальный адрес сегмента, деленный на 16, т.е. без младшей шестнадцатеричной цифры, заносится в один из сегментных регистров. После этого программист получаем доступ к участку памяти, начинающегося с заданного сегментного адреса. Хотя сегмент может располагаться в любом месте памяти и иметь размер до 64 Кбайт, он требует столько памяти, сколько необходимо для выполнения программы.
Распределение памяти при загрузке программы на исполнение показано на рисунке 5.
Рисунок 5 – Анализ памяти простейшей программы
Сегментные регистры автоматически инициализируются следующим образом: ES и DS указывают на начало PSP (что дает возможность, сохранив их содержимое, обращаться затем в программе к PSP), CS – на начало сегмента команд, a SS – на начало сегмента стека. В указатель команд IP загружается относительный адрес точки входа в программу (из операнда директивы end), а в указатель стека SP – величина, равная объявленному размеру стека, в результате чего указатель стека указывает на конец стека (точнее, на первое слово за его пределами). Таким образом, после загрузки программы в память адресуемыми оказываются все сегменты, кроме сегмента данных. Инициализация регистра DS в первых строках программы позволяет сделать адресуемым и этот сегмент.
Процесс отладки и тестирования является неотъемлемой частью создания любой программы. При программировании могут быть допущены ошибки, которые принадлежат к одному из следующих типов:
Функциональное тестирование всех модулей проводилось на протяжении всей разработки программы. Тестирование производилось с помощью отладчика (cv.exe) в стандартной поставке с MASM 6.13. Была выполнена трассировка всей программы.
Чтобы показать, как использовать отладчик при изучении языка ассемблера, исследуем созданную программу var11.asm под управлением отладчика.
Рисунок 6 – Вид отладчика на экране компьютера (после 5 команд)
Структура экрана отладчика разделена на 3 окна:
Исполнение программы в пошаговом режиме: нажатие клавиш F10. Выход из отладчика осуществляется командой Exit из меню.
После запуска программы var11.exe в отладчике, код программы был помещен в свободный сегмент 0BEBh, а данные программы – 0BDBh. Первая команда будет располагаться по адресу 0BEBh:0000h (т.е. CS = 0BEBh, а IP = 0000h). Содержимое регистров СS и IP, в которых хранится базовый адрес сегмента кодов и смещение очередной команды относительно начала сегмента, определяет физический адрес команды, которая должна быть выполнена на следующем шаге.
По нажатию клавиши F10 была выполнена первая команда, которая поместила в регистр AX начальный адрес сегмента данных (AX=0C69h). После выполнения первой команды в регистр IP было помещено значение 0003h, т.е. размер первой команды равен 3 байта и находится по адресу 0C69h:0003h. Вторая команда поместила адрес AX=0C69h в сегментный регистр DS.
Пятая команда интересна тем, что в регистр DX помещается смещение строки ("Massiv:"). На рисунке 6 представлен вид окна отладчика после выполнения первых 5 команд. Нетрудно посчитать, что команда «mov dx,offset mes1» занимает 3 байта (000Dh – 000Ah = 3, разность регистра IP до и после выполнения команды).
Девятая команда обнуляет регистр AL, который будет использоваться для промежуточного результата.
Рисунок 7 – Вид отладчика на экране компьютера (после 9 команд)
Далее идут команды по вычислению результата функции:
mov al, byte ptr Array[7] ;(x7 & x6 & x1)
and al, byte ptr Array[6]
and al, byte ptr Array[1]
mov ah, byte ptr Array[6] ;(x6 & x4 & x2 & x1 & x0)
and ah, byte ptr Array[4]
and ah, byte ptr Array[2]
and ah, byte ptr Array[1]
and ah, byte ptr Array[0]
or al, ah
mov ah, byte ptr Array[7] ;(x7 & x6 & x3 & x1)
and ah, byte ptr Array[6]
and ah, byte ptr Array[3]
and ah, byte ptr Array[1]
or al, ah
Функциональная клавиша F10 отладчика позволяет проследить как меняется результат.
Далее c помощью отладчика можно проследить как происходит условный или безусловный переход в зависимости от значения команды cmp al,0 (т.е. флага ZF).
После отработки программы с помощью стандартного прерывания int 21h (функция 4С00h) происходит выход в DOS.
В результате тестирования программа var11.exe была запущена не менее 5 раз, т.е. исследование происходила на 5 возможных вариантах.
Для
подтверждения результатов в
приложении Г приведена итоговая таблица.
Ассемблер является символическим аналогом машинного языка. По этой причине программа, написанная на ассемблере, должна отражать все особенности архитектуры микропроцессора: организацию памяти, способы адресации операндов, правила использования регистров и т. д. Из-за необходимости учета подобных особенностей ассемблер уникален для каждого типа микропроцессоров.
В данной курсовой работе рассмотрены основные этапы программирования на ассемблере, реализован алгоритм выполнения поставленной задачи, а также выполнена трансляция кода в исполняемый файл. Согласно условию курсовой работы найдено значение логической формулы F=(X7&X6&X1) V (X6&X4&X2X1&X0 ) V (X7&X6&X3&X1) логическими переменными которой являются значения массива из 8 байт. Результат был достигнут благодаря возможностям ассемблера организовывать циклы, условные переходы, а также возможностям отладчика AFDPro, который позволил устранить некоторые небольшие недочеты в исходном модуле программы.
Данная курсовая работа наглядно показала возможности языка низкого уровня Assembler по выполнению тех или иных задач, мною были замечены и проанализированы многие моменты, что касается сравнения языков различных уровней. По моему мнению, ассемблер является достаточно сложным языком программирования. Из проделанной работы я извлек огромный опыт написания различных процедур, циклов, а также работы ключами макроассемблера Microsoft Macro Assembler 6.13.
Блок-схема программы
.model small
.stack 100h
.data
MAXCOUNT=8 ;количество элементов в массиве
CON_IN=0 ;станд. уст-во вывода
CON_OUT=1 ;станд.
уст-во ввода
Array
db 1, 1, 1, 0, 1, 0, 1, 1
mes1 db "Massiv:",0 ;сообщения программы
mes2 db "(x7 & x6 & x1) OR (x6 & x4 & x2 & x1 & x0) OR (x7 & x6 & x3 & x1)",0
mes3 db "FALSE",0
mes4 db "TRUE",0
.code
extrn Clrscr:proc, ;импортируемые функции
Writeint_signed:proc,
ReadKey:proc,
Crlf:proc,
writestring:proc
start:
mov ax, @data
mov ds, ax
mov
es, ax
call clrscr ;очистка экрана
mov dx, offset mes1 ;заносим в dx адрес строки mes1
call
writestring ;вывод строки mes1
lea bp, Array ;в bp заносим указатель на массив Array
call
DrawArray ;вывод массива (парам. функции: bp
Указ. на массив)
xor
al, al ;в Al храним результат функции
mov al, byte ptr Array[7] ;(x7 & x6 & x1)
and al, byte ptr Array[6]
and
al, byte ptr Array[1]
mov ah, byte ptr Array[6] ;(x6 & x4 & x2 & x1 & x0)
and ah, byte ptr Array[4]
and ah, byte ptr Array[2]
and ah, byte ptr Array[1]
and
ah, byte ptr Array[0]
or al, ah
mov ah, byte ptr Array[7] ;(x7 & x6 & x3 & x1)
and ah, byte ptr Array[6]
and ah, byte ptr Array[3]
and
ah, byte ptr Array[1]
or al, ah