Практическое занятие 13
Тема: «Составление программ на языке ассемблера для микропроцессорных систем»
Цель: получение знаний о структуре и основных правилах записи программ на языке Ассемблера для ЭВМ типа IBM PC, а также приобретение практических навыков по составлению простейших программ на языке Ассемблера, их выполнению и отладке.
Теория
Программы на языке Ассемблера представляют собой последовательность операторов, описывающих выполняемые операции. Операторы в свою очередь подразделяются на команды и директивы (или псевдооператоры, псевдокоманды). Каждая команда порождает одну или несколько команд в машинных кодах. Директивы не порождают машинных команд, а лишь информируют транслятор с языка Ассемблера об определенных действиях.
Формат команды языка Ассемблера в общем случае содержит до 4-х полей:
[метка:] команда [поле операндов] [; комментарий]
Обязательным является только поле команды. По крайней мере, один пробел между полями обязателен. Максимальная длина строки - 132 символа.
Метка используется для указания адреса команды и служит для присвоения символического имени первому байту области памяти, в котором будет записан машинный эквивалент команды. Метки могут содержать:
- буквы от A до Z, причем Ассемблер не делает разницы между строчными и прописными буквами;
- цифры от 0 до 9;
- спец. символы: '?', '.'(только первый символ), '@'(коммерческое эт), '$', '_'.
Первым символом в метке должна быть буква или специальный символ. Максимальная длина метки - 31 символ.
Поле команды содержит имя команды, например, MOV - команда пересылки, ADD - команда сложения и другие.
Операнды определяют:
- начальные значения данных;
- элементы, над которыми выполняется действие.
Пример:
MOV AX, 5; команда MOV заносит в регистр AX значение 5.
В поле операнда, если оно присутствует, может быть один или два операнда. Между собой операнды отделяются запятой. В командах с двумя операндами первый представляет собой приемник, а второй - источник. Источник никогда не изменяется, приемник изменяется почти всегда.
Комментарий начинается с символа ';' в любом месте программы. Все символы справа от символа ';' до конца строки воспринимаются Ассемблером как комментарий.
Директивы могут иметь до 4-х полей:
[метка] директива [операнд] [; комментарий]
Наиболее употребительные директивы можно разделить на две группы: директивы данных и директивы управления листингом. Директивы данных в свою очередь делятся на пять групп:
- директивы определения идентификаторов;
- директивы определения данных;
- директивы внешних ссылок;
- директивы определения сегмента/процедуры;
Существует две директивы определения идентификаторов: EQU и '='. EQU присваивает имя выражению постоянно, а '=' - временно и его можно переопределить.
Существуют следующие директивы определения данных:
- DB - определить байт;
- DD - определить двойное слово;
- DW - определить слово;
- DT - определить 10 байт.
Обычно DB и DW резервируют память под переменные, а DD и DT - под адреса. В любом случае можно указать начальное значение или знак '?' только для резервирования памяти. Операция DUP позволяет повторять одно и тоже значение несколько раз.
Пример:
PEREM DB 4 DUP(?); директива резервирует четыре байта в памяти под переменную PEREM.
Если перечислять значения переменной через запятую, то тем самым определяется таблица данных.
Пример:
TABL DW 3,4,5 ; директива выделяет область памяти с именем TABL длиной три слова
;и заносит в первое слово значение 3, во второе значение 4, в третье слово - значение 5.
Директивы определения сегмента делят исходную программу на сегменты. В программе на языке Ассемблера возможно 4 вида сегментов:
- сегмент данных;
- сегмент стека;
- сегмент команд;
- дополнительный сегмент.
По крайней мере один сегмент - сегмент команд - должен присутствовать в каждой программе.
Существует две директивы определения сегмента: SEGMENT и ENDS, а также директива ASSUME, которая устанавливает для Ассемблера соответствие между конкретными сегментами и сегментными pегистpами.
Пример:
DATASG SEGMENT PARA 'DATA' ;директива определяет начало сегмента с именем DATASG, а ;директива
DATASG ENDS ;конец этого сегмента.
Директива
ASSUME CS:CODESG,DS:DATASG
указывает Ассемблеру, что сегмент CODESG будет адресоваться с помощью сегментного регистра CS, а сегмент DATASG - с помощью сегментного регистра DS.
Директивы PROC и ENDP определяют начало и конец процедуры. Процедура может иметь атрибут дистанции NEAR или FAR. Процедура с атрибутом NEAR может быть вызвана только из того сегмента команд, в котором она определена, а процедура с атрибутом FAR может быть вызвана и из другого сегмента команд. Например, директива
FUN PROC NEAR
определяет начало процедуры FUN с атрибутом дистанции NEAR, а
директива
FUN ENDP
конец этой процедуры. Программа на Ассемблере имеет атрибут FAR.
Директивы внешних ссылок PUBLIC и EXTRN делают возможным использование переменных и процедур, определенных в разных файлах.
Директива управления трансляцией END отмечает конец исходного модуля, обязательно присутствует в каждом модуле.
Директивы управления листингом PAGE и TITLE могут быть использованы для определения формата вывода распечаток программ и выдачи заголовков.
Таким образом, типовая структура программы на языке Ассемблера для ЭВМ типа IBM PC выглядит следующим образом:
TITLE ;заголовок программы
PAGE 60,132 ; определение сегмента стека
STACKSG SEGMENT PARA STACK 'STACK'
DB 64 DUP(?) ; область стека, не менее 32 слов
STACKSG ENDS ; конец сегмента стека
DATASG SEGMENT PARA 'DATA' ; определение сегмента данных
; здесь можно поместить, если необходимо, директивы определения
DATASG ENDS ;конец сегмента данных
; Определение сегмента команд (основная программа)
CODESG SEGMENT PARA 'CODE'
ASSUME CS:CODESG, DS:DATASG, SS:STACKSG
ENTRY PROC FAR
; Инициализировать программу
PUSH DS ; сохранить в стеке адрес возврата
SUB AX,AX ; обнулить регистр AX
PUSH AX ; занести в стек нулевое смещение для адреса возврата
; Инициализировать адрес сегмента данных
MOV AX,DATASG ; занести адрес сегмента
MOV DS,AX ; данных в регистр DS
; Программа
...
POP AX;
POP DS; восстановили регистры AX и DS
RET ; вернутся в MS-DOS
ENTRY ENDP
CODESG ENDS
END ENTRY
В данном фрагменте показана группа команд PUSH DS ... MOV DS,AX, которая является стандартной для программ на Ассемблере и обеспечивает возврат управления в MS-DOS после выполнения программы. Команда RET обеспечивает выход из программы и передачу управления MS-DOS.
Пример выполнения задания
В отличие от языков программирования высокого уровня, язык Ассемблера поставляется без среды разработки программ. Поэтому разработчику приходится самостоятельно контролировать весь процесс создания программы, который включает в себя следующие этапы:
1. Постановка задачи (точное и подробное описание функциональности будущей программы, а также описание всех входных и выходных данных и способа их передачи программе);
2. Разработка алгоритма программы (построение блок-схемы, текстовое или математическое описание решения);
3. Формализация алгоритма (запись алгоритма на языке программирования). Создание текстового файла программы с расширением .asm (например, my.asm). Отсутствие среды разработки позволяет программисту самостоятельно выбрать текстовый редактор для написания кода программы. Для этой цели подойдет любой текстовый редактор с нумерацией строк, например Блокнот или редактор, встроенный в оболочку FAR-менеджер.
4. Трансляция программы. Трансляция - процесс перевода программы из текстового вида в машинный код. При использовании транслятора фирмы Borland необходимо выполнить команду:
tasm my.asm
т.е. запускаем транслятор tasm и передаем с командной строки имя файла, содержащего программу. Если программа имеет синтаксические ошибки, транслятор выдаст сообщение об ошибке с указанием номера строки и описанием для каждой ошибки (нужно вернуться на этап №3 и исправить синтаксические ошибки). В случае успешной трансляции будет создан файл, содержащий объектный код программы my.obj, который ещё не является исполняемым модулем.
5. Компоновка программы. Компоновка - создание из файла объектного кода исполняемого модуля.
tlink my.obj
В качестве параметра компоновщик tlink принимает имя файла содержащего объектный код программы (в нашем случае - my.obj). В случае успешной компоновки будет создан исполняемый модуль my.exe
6. Запуск и тестирование исполняемого модуля программы. На данном этапе необходимо проверить, соответствует ли написанная программа постановке задачи, выполненной на этапе №1. Неправильная работа программы говорит об алгоритмической ошибке (семантическая ошибка), поэтому для успешного её устранения следует вернуться на этап разработки алгоритма (этап №2).
Написание первой программы на языке ассемблера
1. Постановка задачи. Написать программу, которая выводит на экран строчку "Привет!".
2. Разработка алгоритма программы. Алгоритм линейный, разработки не требует.
3. Формализация (запись) алгоритма
В текстовом редакторе создаем файл privet.asm и записываем в него следующий код (без номеров строк) :
Вариант 1:
|
1 |
|
data segment |
;описание сегмента данных |
|
|
2 |
|
|
mes db 'Привет!$' |
;строка для вывода на экран. '$' - признак конца строки |
|
3 |
|
data ends |
;конец сегмента данных |
|
|
4 |
|
code segment |
;начало сегмента кода |
|
|
5 |
|
start: |
;метка start - начало нашей программы |
|
|
6 |
|
|
assume cs:code, ds: data |
;директива компилятора |
|
7 |
|
|
mov ax, data |
;настройка сегмента данных |
|
8 |
|
|
mov ds, ax |
|
|
9 |
|
|
mov ah, 9 |
;функция №9 прерывания 21h - вывод строки на экран |
|
10 |
|
|
lea dx, mes |
;берём адрес строки |
|
11 |
|
|
int 21h |
;вызов прерывания для вывода строки |
|
12 |
|
|
mov ax, 4c00h |
;функция завершения программы |
|
13 |
|
|
int 21h |
;завершаем программу |
|
14 |
|
code ends |
;конец сегмента кода |
|
|
15 |
|
end start |
;конец программы с точкой входа start |
|
4.
Компиляция программы
tasm privet.asm
5.
Компоновка программы
tlink privet.obj
6.
Запуск и тестирование
privet.exe
Переход на новую строку
Для организации перехода на новую строку достаточно вывести на экран символы перевода строки и возврата каретки (CR/LF). Эти символы имеют коды 10 и 13. Если в нашей программе необходимо после вывода строки перейти на новую, то для этого достаточно переписать вторую строку программы:
mes2 db 'Выводим строку и переходим на новую...', 10, 13, '$'
Переход на новую строку можно выполнить и до вывода сообщения на экран:
mes3 db 10, 13, 'Выводим с новой строки...$'
Вариант 2:
|
text segment |
;Начало сегмента команд |
|
|
assume CS:text,DS:data |
;Сегментный регистр CS будет указывать на сегмент команд, а сегментный регистр DS - на сегмент данных |
|
|
start: mov AX,data |
;Адрес сегмента данных сначала загрузим в АХ, |
|
|
mov DS,AX |
;а затем перенесем из АХ в DS |
|
|
mov AH,09h |
;Функция MS-DOS 9h вывода на экран |
|
|
mov DX,offset mesg |
;Адрес выводимого сообщения должен быть в DX |
|
|
int 21h |
;Вызов MS-DOS |
|
|
mov AH,4Ch |
;Функция 4Ch завершения программы |
|
|
mov AL, 0 |
;Код 0 успешного завершения |
|
|
int 21h |
;Вызов MS-DOS |
|
|
text ends |
;Конец сегмента команд |
|
|
data segment |
;Начало сегмента данных |
|
|
mesg db 'Hello world!$' |
;Выводимый текст |
|
|
data ends |
;Конец сегмента данных |
|
|
stk segment stack |
;Начало сегмента стека |
|
|
db 256 dup (0) |
;Резервируем 256 байт для стека |
|
|
stk ends |
;Конец сегмента стека |
|
|
end start |
;Конец текста программы с точкой входа start |
Ход работы
1. Написать программу, которая выводит одно под другим следующие сообщения:
Привет!
Меня зовут ФИО студента!
Я с удовольствием буду изучать Ассемблер!
Материалы на данной страницы взяты из открытых источников либо размещены пользователем в соответствии с договором-офертой сайта. Вы можете сообщить о нарушении.