Конспект лекций по курсу Ассемблер (Алещенко) (1002288), страница 5
Текст из файла (страница 5)
Предложения ЯА делятся на три вида: комментарии, инструкции и директивы.
-
Комментарии не влияют на смысл программы, при трансляции Ассемблер их игнорирует. Комментарием считается любая строка или конец строки, начиная с точки с запятой, либо пустая строка.
Например,
; начало процесса
ADD BX, 20; BX := BX + 20d
Можно организовать комментарий, состоящий из нескольких строк, он должен начинаться с директивы
COMMENT {маркер} {текст}
…
{текст}{маркер} [{текст}]
где {маркер} – любой символ, кроме пробела, расположенный после COMMENT,
прямоугольными скобками оформляются необязательные элементы.
Последней строкой комментария считается строка, содержащая тот же маркер в любой позиции.
Это позволяет временно исключить фрагмент программы из обработки.
-
Инструкции ЯА были в основном рассмотрены выше.
Общий вид инструкции ЯА:
[{метка}:] {мнемоника} [{операнды}] [;{комментарий}]
где {мнемоника} – является обязательной частью инструкции, она относится к ключевым словам;
{операнды} – если они есть, то разделяются запятыми, обычно записываются в виде выражений, содержащих указания на режим адресации.
Например,
SYM: mov AH, S[SI+2]; AH := содержимое ОП по адресу [S+[SI]+2]
mov CX, [126h]; CX := содержимое ОП по адресу [126h]
add Z, -300; Z := Z + (- 300d)
Выражения в квадратных скобках позволяют вычислить адрес операнда как смещение относительно DS.
Непосредственный операнд не может быть представлен выражением.
-
Директивы не порождают машинные коды и используются на этапе ассемблирования.
Директивы в ЯА бывают трех видов:
-
директивы определения данных и резервирования памяти;
-
директивы определения имен;
-
директивы управления ассемблированием (т.е. трансляцией программы).
Общий вид директивы ЯА
[{имя}] {название директивы} [{операнды}]
а) Директивы определения данных и резервирования памяти используются для определения и инициализации основных единиц памяти:
DB – (declare byte) декларация последовательности байтов;
DW – (declare word) декларация последовательности слов;
DD – (declare double word) декларация последовательности двойных слов.
Рассмотрим эти директивы на примере декларации байтов
[{имя}] DB {начальные значения}
где {имя} переменной заменяет численное значение адреса распределяемых ячеек памяти, если оно есть, то относится к первому байту данной области ОП (ООП).
DB – позволяет определить один или несколько последовательно расположенных в ОП байтов, содержащих значения, перечисленные в поле начальных значений.
Например,
Line DB ‘SYMBOL буквы‘; описана последовательность 12 байтов
M DB 2
DB -4
Две последние декларации описывают общую ООП из 2 байтов.
Начальные значения разделяются запятыми, если отдельному байту на присваивается начальное значение, то в списке начальных значений записывается «?».
Например,
A DB 0f2h,-2,?,’*’ ; описываются 4 байта, содержащие следующую информацию:
F2h | FEh | Что было | 2Ah |
А | А+1 | А+2 | Код ’*’ |
б) Директивы определения имен.
Директива EQU (equal) позволяет присвоить символическое имя часто используемой конструкции.
Общий вид : {имя} EQU {выражение}
где {имя}- может быть определено только один раз в программе, оно сохраняет свое значение во всей программе, если не будет отменено директивой PURGE;
{выражение} – может определять константы, мнемоники, регистры, адреса.
Ассемблер автоматически заменяет имя выражением(его значением).
Например,
K EQU 1024; K=1024
Stap EQU xor ax, ax ; Stap замещается текстом команды
Prop EQU ‘type enter’ ; Prop замещается текстом сообщения
Существует другой вид той же директивы :
{имя} = {константное выражение}
Константа, описанная таким образом, может менять свое значение в разных частях текста программы.
Например,
X = 10
A DW X ; эквивалентно A DW 10
…
X = X+4
B DB X ; A DW 14d
Директива PURGE используется для удаления имени из таблицы имен, которую формирует ассемблер, и для его переопределения.
Общий вид: PURGE {имя}
Например,
PURGE Stap ; После этой директивы имя Stap можно переопределить.
Директива LABEL создает новое имя для любых ячеек памяти, независимо от содержимого и предполагаемого использования, т.е. переопределяет атрибут имени, расположенного непосредственно после этой декларации.
Общий вид
{имя} LABEL {тип} , где
три первых атрибута используются для имен ячеек памяти с данными, а два последних - для меток команд.
Например,
Barb LABEL BYTE
Barw DW 253Bh
…
mov AL, Barb; AL := ОП[Barb] (размер - 1 байт)
mov BX, Bar W; BX := ОП[Barb W] - слово
Таким образом можно обращаться как к слову целиком, так и к отдельному байту.
в) Директивы управления ассемблированием или структурные директивы
Перечислим основные директивы этой группы, необходимые для оформления программы на ЯА:
SEGMENT – определение сегмента;
ENDS – конец сегмента;
END – конец исходного файла;
ASSUME – определение сегментных регистров;
PROC – определение процедуры;
ENDP – конец текста процедуры.
Эти директивы на примере необходимого оформления структуры программы. Кроме того есть директивы набора команд (инструкций) для конкретных МП :
.8086 – используются по умолчанию
.8087
.286 – 286 процессора набор команд
.286p ; защищенный режим
.287 и т.д.
Эти директивы могут быть помещены в начале исходного файла программы и гарантируют ассемблирование всех команд в текущем файле. Более поздние версии МП включают в себя команды предыдущих версий.
Структура программы на языке Ассемблера
Исходный файл на ЯА состоит из сегментов. В простейшем случае это – один сегмент, который содержит обязательные элементы.
{мет. сегм.} SEGMENT ’code’
ASSUME CS:{ мет. сегм.}, DS:{ мет. сегм.}
{мет. начала} MOV AX, { мет. сегм.};
MOV DS,AX;
………………
MOV AX,{код функции};
INT 21h
……………
… DW …
… DB …
{ мет. сегм.} ENDS
END { мет. начала}
Рассмотрим директивы оформления программы:
1) директива SEGMENT для ассемблеров MASM или TASM имеет одинаковую структуру
{мет. сегм.} SEGMENT [{счетн.}] [{комб.}] [‘{класс}’] ,где
{мет. сегм.} - это имя сегмента, которое трактуется как метка, т.к. используется для передачи управления. Атрибуты необязательны, но, если они есть, то очередность должна сохраняться.
{счетн.} – определяет метод выравнивания данного сегмента, т.е. начальный адрес сегмента.
Возможны следующие варианты:
Значение атрибута | Граница | Использование | Примечания | ||
Название | Нач. адрес | MASM | TASM | ||
Byte | Байт | Любой | + | + | Не рекомендуется |
Word | Слово | Четный | + | + | |
Para | Параграф | Кратный 16 | + | + | По умолчанию |
Page | Страница | Кратный 256 | + | + | |
Dword | Двойное слово | Кратный 4 | _ | + |
{комб.} – показывает, как данный сегмент должен объединяться с другим, имеющим ту же метку, но из другого исходного файла.
Ограничение: размер области ОП, которая получается в результате объединения сегментов, не должна превышать 64 Кбайта. Если нет атрибута {комб.}, то сегмент не объединяется с другими.
Возможны варианты атрибута: PRIVATE, PUBLIC, COMMON, STACK и др.
‘{класс}’ – указывается в апострофах, помогает компоновщику определить нужный порядок расположения сегментов при сборке из разных модулей. При этом все сегменты с одинаковым классом объединяются в один последовательно, а с различными классами – располагаются, как правило, в алфавитном порядке.
Часто используются классы:
‘Code’ – сегмент команд;
‘Stack’ – сегмент команд;
‘Data’ – сегмент данных.
Класс сегмента необходимо указывать для правильной обработки файла.
Например, MASM требует наличия класса ‘Code’, т.к. без этого не может работать отладчик Code View (CV), а компоновщик TLINK, входящий в TASM, не инициализирует сегмент стека, если не объявлен класс ‘Stack’.
2) директива ASSUME нужна для выполнения команд программы, которые неявно ссылаются на сегментные регистры МП (т.е. в примере – DS и CS). Она обеспечивает передачу адресов сегментов с соответствующими именами в сегментные регистры.
Общий вид
ASSUME CS:{ мет.}[, {сег. рег.}:{ мет.}]
В приведенном примере эта директива означает, что DS и CS указывают на один и тот же сегмент, причем в CS адрес начала сегмента загружается автоматически, а в DS для этого требуются обычно две инструкции в самом начале сегмента:
mov AX,{метка}
mov DS,AX
ASSUME может быть расположен до начала первого сегмента. В многосегментных программах ASSUME может описывать следующие сегменты
Сег.рег. | Сегмент | Загрузка адреса |
CS | Рг сегмента команд | автоматическая |
DS | Рг сегмента данных | в программе |
ES | Рг доп. сегмента данных | в программе |
SS | Рг сегмента стека | автоматическая |
3) Директива ENDS указывает на конец текста сегмента. Общий вид
{ мет. сегм.} ENDS
4) Директива END указывает на конец текста исходного модуля (ИМ). Общий вид
END { мет. начала}
где { мет. начала} – пусковой адрес, т.е. метка первой выполняемой строки ИМ, которой передается управление после компоновки.
Эта директива нужна, т.к. декларации описания ООП (DB, DW …) могут располагаться в начале или в конце сегмента команд, причем рекомендуется – в начале. Декларации можно вставлять и в текст между командами, но это – не корректно.