Процедуры формирования программы
Начальной процедурой создания программы на языке Ассемблера является ввод исходного текста программы в файл с расширением .asm. При этом может быть использован любой текстовый редактор, сохраняющий текст в виде стандартных кодов ASCII, например, редактор NC или блокнот. Основное требование к редактору, заключается в том, чтобы он (редактор) не вставлял посторонних символов (специальных символов форматирования).
Следующим шагом формирования программы является компиляция, которая носит специфическое название ассемблирование.
Результатом выполнения этого этапа является программа в машинных кодах с расширением .obj, или, иначе, объектная программа, уже “понятная” микропроцессору. Естественно перевод состоится лишь в том случае, если исходный текст программы не содержит ошибок.
Однако объектная программа еще не является законченной и исполняемой, т.к. в ней определены не все адреса (программа не является “перемещаемой”) и не объединены части (блоки) программы, которые могут транслироваться отдельно с целью более простой отладки. Преобразование объектной программы в исполняемую (компоновка) выполняется загрузчиком (редактором связей) LINK.
Только после этого получается исполняемый файл.
Порядок действий в FASM
Создайте новый файл и сохраните его с расширением .asm
Выберите пункт меню Run Program.
Просмотрев полученные результаты, закройте окно исполняемого файла.
Синтаксис команд
Рассмотрим формат команды ассемблера: [Метка:] Мнемокод [операнд] [;комментарий]
Обязательным здесь является только мнемокод. В зависимости от команды может не быть операндов, может быть один или два операнда.
Метка - служит для присвоения имени команде. На эту метку можно будет ссылаться из любой части программы. Она может содержать до 31 символа и заканчиваться двоеточием и содержать символы алфавита от a до Z. и от a до z, цифры от 0 до 9 и символы ?, ., @,, _, $. Метка не должна начинаться с цифры. Если используется «.», то она должна быть первым символом метки. Имя метки не должно совпадать с названием команд. В метку не должны вставляться пробелы.
Комментарии — должны быть отделены от команд ;. Это комментарии к команде, программе и блоку команд.
Мнемокод - это имя команды МП.
Поле операндов — в поле операндов может быть0, 1 или 2 операнда в зависимости от типа команды. Операнд - часть команды, макрокоманды или директивы ассемблера, обозначающие объекты, над которыми производятся действия. Операнды ассемблера описываются выражениями с числовыми и текстовыми константами, метками и идентификаторами переменных с использованием знаков операций и некоторых зарезервированных слов.
Если в команде 2 операнда, то первый операнд называется приемником, а второй источником.
Например:
MOV AX, CX ; содержимое регистра cx перемещается в ax
Команда Mov
Команда пересылки данных. Копирует содержимое источника в приёмник, источник не изменяется.
Например: mov ax, 1 присваивает регистру ax значение 1.
Операнды команды mov могут быть как регистрами, так и переменными, но одновременно оба операнда не могут быть переменными.
Примеры показывают все пять возможных ситуаций:
регистр-регистр;
mov ax,bx
mov ah,al
память-регистр;
mov [000ah],ax
регистр-память;
mov ax, [000ah]
регистр- непосредственное значение;
mov ax,279
Сложение и вычитание
Команды ADD и SUB выполняют сложение и вычитание байтов или слов, содержащих двоичные данные. Вычитание выполняется в компьютере по методу сложения с двоичным дополнением: для второго операнда устанавливаются обратные значения бит и прибавляется 1, а затем происходит сложение с первым операндом. Во всем, кроме первого шага, операции сложения и вычитания идентичны.
Примеры показывают все пять возможных ситуаций:
сложение/вычитание регистр-регистр;
add ax,bx
add ah,al
сложение/вычитание память-регистр;
sub [000ah],ax
сложение/вычитание регистр-память;
add ax, [000ah]
сложение/вычитание регистр- непосредственное значение;
add ax,279
sub ch,3
Поскольку прямой операции память-память не существует, данная операция выполняется через регистр.
Умножение
Операция умножения для беззнаковых данных выполняется командой MUL, а для знаковых - IMUL. Ответственность за контроль над форматом обрабатываемых чисел и за выбор подходящей команды умножения лежит на самом программисте. Существуют две основные операции умножения:
"Байт на байт". Один из множителей находится в регистре AL, а другой в байте памяти или в однобайтовом регистре. После умножения произведение находится в регистре AX. Операция игнорирует и стиpает любые данные, которые находились в регистре AH.
"Слово на слово". Один из множителей находится в регистре AX, а другой - в слове памяти или в регистре. После умножения произведение находится в двойном слове, для которого требуется два регистра: старшая (левая) часть произведения находится в регистре DX, а младшая (правая) часть в регистре AX. Операция игнорирует и стирает любые данные, которые находились в регистре DX.
В единственном операнде команд MUL и IMUL указывается множитель. Рассмотрим следующую команду:
Пример:
mov bx,10
mov al,2
mul bx ;ax=2*10=20=0014h: ah=00h al=14h
Знаковое умножение: Команда IMUL
Команда IMUL умножает знаковые числа.
mov ax,8
mov bx,-1
imul bx ; dx:ax=-8=0fffffff8h=0014h: dx=0ffffh ax=0fff8h
Таким образом, если множимое и множитель имеет одинаковый знаковый бит, то команды MUL и IMUL генерируют одинаковый результат. Но, если сомножители имеют разные знаковые биты, то команда MUL вырабатывает положительный результат умножения, а команда IMUL - отрицательный.
Деление
Операция деления для беззнаковых данных выполняется командой DIV, a для знаковых - IDIV. Ответственность за подбор подходящей команды лежит на программисте. Существуют две основные операции деления:
Деление "слова на байт". Делимое находится в регистре AX, а делитель - в байте памяти или в однобайтовом регистре. После деления остаток получается в регистре AH, а частное -в AL. Так как однобайтовое частное очень мало (максимально+255 для беззнакового деления и +127 для знакового), то данная операция имеет ограниченное использование.
Деление "двойного слова на слово". Делимое находится в регистровой паре DX:AX, а делитель - в слове памяти или в регистре. После деления остаток получается в регистре DX, а частное в регистре AX. Частное в одном слове допускает максимальное значение +32767 для беззнакового деления и +16383 для знакового.
В единственном операнде команд DIV и IDIV указывается делитель.
Пример
Mov ax,100
Mov bh,2
Div bh ; 100 div 2=50, ah=0 al=50
Система прерываний
Для работы в режиме DOS необходимо пользоваться системой прерываний.
Программа, запрашивающая сервис DOS, должна подготовить всю необходимую информацию в регистрах и управляющих блоках, указать в регистре AH номер желаемой функции DOS и затем вызвать прерывание INT 21H.
Рассмотрим некоторые функции используемые в лабораторной работе.
Функция 01h (Считать символ из STDIN с эхом, ожиданием и проверкой на Ctrl+Break)
Вход: |
АН |
01h |
| |
Выход: |
AL |
С клавиатуры |
Эта функция считывает (ожидает) символ со стандартного входного устройства - STDIN (например, с клавиатуры) и отображает этот символ на стандартном выходном устройстве - STDOUT (например, на мониторе). При считывании символа его отображение на устройстве вывода называют "эхом". При распознавании нажатия сочетания клавиш Ctrl+Break выполняется прерывание INT 23h.
Функция 02h (Вывести символ на STDOUT с проверкой на Ctrl+Break)
Вход: |
АН |
02h |
DL |
символ, выводимый на устройство стандартного вывода | |
Выход: |
Нет |
--- |
Эта функция посылает символ из регистра DL на устройство стандартного вывода. В DL можно записать как ASCII-код символа, так сам символ. В последнем случае символ заключается в одинарные кавычки.
Функция 08h (Считать символ из STDIN без эха, с ожиданием и проверкой на Ctrl+Break)
Вход: |
АН |
08h |
Выход: |
AL |
код символа |
Эта функция считывает (ожидает) символ из стандартного входного устройства и возвращает этот символ в регистр AL.
Функция 09h (Записать строку в STDOUT с проверкой на Ctrl+Break)
Вход: |
АН |
09h |
DS:DX |
адрес строки | |
Выход: |
Нет |
--- |
Эта функция выводит на стандартное устройство вывода (например, на монитор) строку символов. Адрес строки (первого символа строки) должен быть предварительно записан в DS:DX. Строка должна ОБЯЗАТЕЛЬНО заканчиваться символом $ (24h), который не будет выведен в STDOUT.