Директивы Ассемблера
Группа директив для указания типа процессора
Директивы указания типа процессора задают набор используемых инструкций.
.186, .286, .386, .486, .586, .686 - использование инструкций процессоров 80186, 80286, 80386, 80486, Pentium, Pentium Pro
.286P, .386P, .486P, .586P, .686P - использование инструкций процессоров, включая инструкции защищенного режима
.287, .387 - использование инструкций математического сопроцессора
Пример кода:
; по-умолчанию в начале ставится режим .8086 .model small .stack 100h .code .486 ; указываем режим 80486, чтобы иметь возможность использовать команду BSWAP start: mov edx, 01020304h bswap edx mov ax, 4C00h int 21h end start
Директивы для указания сегментов
Директива SEGMENT
Определяет сегмент с заданным именем name. Если сегмент с таким именем уже был определен ранее, то данный сегмент интерпретируется как продолжение предыдущего.
Необязательные параметры:
align - определяет выравнивание начального адреса сегмента на границу, определяемую значением параметра. Возможные значения:
BYTE | выравнивание не выполняется. Сегмент может начинаться с любого адреса памяти |
WORD | выравнивание на границу слова (2 байта) |
DWORD | выравнивание на границу двойного слова (4 байта) |
PARA | выравнивание по границе параграфа (16 байт). Используется по-умолчанию. |
PAGE | выравнивание на границу в 256 байт |
combine - определяет, как сегменты с одним и тем же именем, но из различных модулей должны комбинироваться во время компоновки. Возможные значения:
PUBLIC | заставляет компоновщик соединить все сегменты с одинаковым именем. Новый объединенный сегмент будет целым и непрерывным. Все адреса (смещения) объектов будут вычисляться относительно начала этого нового сегмента |
STACK | выполняется конкатенация всех сегментов с одним и тем же именем для формирования одного непрерывного сегмента, затем регистр SS инициализируется значением начала сегмента, а SP - длиной сегмента. Если не указано ни одного сегмента стека, компоновщик выдаст предупреждение, что стековый сегмент не найден. Если сегмент стека создан, а комбинированный тип STACK не используется, программист должен явно загрузить в регистр SS адрес сегмента (подобно тому, как это делается для регистра DS) |
COMMON | данный сегмент и все другие сегменты с этим именем помещаются по одному адресу. Все сегменты с данным именем будут перекрываться и совместно использовать память. Размер полученного в результате сегмента будет равен размеру самого большого сегмента |
AT address | сегмент помещается по абсолютному адресу параграфа address |
PRIVATE | данный сегмент не комбинируется с другими сегментами. Используется по-умолчанию |
use - определяет разрядность сегмента. Возможные значения:
USE16 | сегмент с 16-разрядной адресацией. Максимальный размер сегмента 64 Кб |
USE32 | сегмент с 32-разрядной адресацией. Максимальный размер сегмента 4 Гб. В модели памяти FLAT используется по-умолчанию |
class - задает строковое значение "класса" сегмента. Компоновщик объединяет вместе в памяти все сегменты с одним и тем же именем класса.
Директива ENDS
Определяет конец сегмента.
Директива ASSUME
Задает сегментный регистр, который будет использоваться для вычисления действующего адреса для всех меток и переменных, определенных для сегмента или группы сегментов с указанным именем.
Пример кода:
.386 stack16 segment stack db 100 dup(0) ends data16 segment var db 0 ends code16 segment use16 'code' assume cs:code16, ds:data16, ss:stack16 start: mov var,00h mov ax,4C00h int 21h ends end start
Директивы для упрощенного указания сегментов
Директива .MODEL
Задает модель памяти для упрощенных директив определения сегментов.
Параметры:
memory-model - модель памяти. Возможные значения:
TINY | Код, данные и стек объединены в одну группу с именем DGROUP и размером до 64 Кб. Используется для создания программ формата .com. Некоторые языки эту модель не поддерживают. СS=DS=SS=DGROUP |
SMALL | Код занимает один сегмент, данные и стек объединены в одну группу с именем DGROUP (хотя для описания могут использоваться разные сегменты). Эту модель обычно используют для большинства программ на ассемблере. CS=_text DS=SS=DGROUP |
MEDIUM | Код занимает несколько сегментов, по одному на каждый объединяемый программный модуль. Все ссылки на передачу управления — типа far (вызов подпрограмм). Данные и стек объединены в одной группе DGROUP; все ссылки на них — типа near (для доступа к данным используется только смещение). CS=<модуль>_text DS=SS=DGROUP |
COMPACT | Код находится в одном сегменте, данные и стек в группе DGROUP и могут занимать несколько сегментов, так что для обращения к данным требуется указывать сегмент и смещение (ссылка на данные — типа far). CS=_text DS=SS=DGROUP |
LARGE | Код может занимать несколько сегментов, по одному на каждый объединяемый программный модуль. Стек и данные находятся в группе DGROUP. Для ссылки на данные используются дальние указатели -far. CS=<модуль>_text DS=SS=DGROUP |
HUGE | То же, что модель LARGE |
FLAT | То же, что и модель TINY, но для 32-битных сегментов |
language-type - тип языка программирования. Возможные значения:
C | Аргументы передаются через стек, справа налево. Стек очищает вызывающая программа. |
PASCAL, BASIC | Аргументы передаются через стек, слева направо. Стек очищает вызываемая подпрограмма. |
STDCALL | Аргументы передаются через стек, справа налево. Стек очищает вызываемая подпрограмма. |
stack-option - организация стека. Возможные значения для 16 бит: NEARSTACK, FARSTACK. Для 32 бит не используется. Указание NEARSTACK группирует сегменты стека в один физический сегмент (DGROUP) вместе с данными. Регистр сегмента стека SS назначается на тот же адрес что и регистр сегмента данных DS. FARSTACK не группирует стек с сегментом данных DGROUP; таким образом регистр SS не будет равен регистру DS.
Директива .CODE или CODESEG
Определяет начало сегмента кода. Если задали среднюю или большую модель памяти, то за директивой может следовать необязательное имя, которое указывает имя сегмента. По-умолчанию имя сегмента _TEXT.
Директива .DATA или DATASEG
Определяет начало инициализированного сегмента данных.
Директива .DATA?
Определяет в модуле начало неинициализированного сегмента данных.
Директива .CONST
Определяет начало сегмента данных-констант.
Сегменты .DATA, .DATA?, .CONST помещаются в одну группу с именем DGROUP
Директива .STACK или STACK
Определяет начало сегмента стека, выделяя количество байт, заданное параметром. Если размер не указывается, выделяется 1024 байт.
Пример кода:
.model small,stdcall .stack 100h .data str db 'Hello, world!',0 .code start: mov ax,4C00h int 21h end start
Группа директив для резервирования памяти
DB, DW, DD, DF, DP, DQ, DT - Резервирование памяти с размером соответственно 1 байт (DB), 2 байта (DW), 4 байта (DD), 6 байт (DF, DP), 8 байт (DQ) и 10 байт (DT)
Резервирует область памяти, заданного директивой размера, с указанным именем, и инициализирует значением выражения. Выражение может быть числом, строкой символов, специальным символом "?", а также выражением с использованием директивы DUP.
Повторяет операцию выделения памяти для указанных данных столько раз, сколько задано значением счетчика
Пример кода:
val1 dw ? val2 db 10 dup(0) val3 dd 4 dub(0FFFFFFFFh) val4 db 'Test string',0 val5 db 2 dup(0Fh), 4 dup(?)
Директива STRUC (STRUCT)
Определяет структуру данных с заданным именем, содержащую поля. В каждом поле для определения его размера используются обычные директивы выделения данных (DB, DW и т.д.). Поля структуры могут быть именованными или нет.
Директива ENDS
Определяет конец структуры.
Пример кода:
str1 struc db 10h field1 dw ? field2 db 5 dup(?) str1 ends
Директива UNION
Определяет объединение структур данных, имеющих одно и то же имя. Объединение означает, что структуры будут располагаться по одному и тому же адресу в памяти. Закрытие объединений делается так же как и для структур - с помощью директивы ENDS.
Пример кода:
str1 union db ? db ? db 2 dup(0) str1 ends str2 union dw ? dw ? str2 ends
Группа директив модификации размера указателей
Используются когда возникает неоднозначность в размере операнда команды. Например когда в ячейку памяти записывается число, то компилятор не может определить число какого размера требуется записать, и в этом случае требуется укзать директиву модификации размера.
BYTE [PTR] - Приводит адресное выражение к размеру в байт
DWORD [PTR] - Приводит адресное выражение к размеру в двойное слово (4 байта)
FAR [PTR] - Приводит к тому, что адресное выражение будет дальним указателем
FWORD [PTR] - Приводит к тому, что адресное выражение будет иметь размер 32-разрядного дальнего указателя
NEAR [PTR] - Приводит к тому, что адресное выражение будет ближним указателем на код
PWORD [PTR] - Приводит к тому, что адресное выражение будет иметь размер 32-разрядного дальнего указателя
QWORD [PTR] - Приводит к тому, что адресное выражение будет иметь размер четверного слова (8 байт)
SHORT - Приводит к тому, что выражение будет указателем на код короткого типа (в границах -128 до +127 байт от текущего адреса программы)
TBYTE [PTR] - Приводит к тому, что адресное выражение будет иметь размер 10 байт
WORD [PTR] - Приводит адресное выражение к размеру в слово (2 байта)
Пример кода:
mov es:[di], dword ptr 0
Директивы определения процедур
Директива PROC
Определяет начало процедуры с указанным именем.
Необязательные параметры:
язык - определяет, из какого языка выполняется вызов для доступа к данной процедуре: C, PASCAL, BASIC, STDCALL или NOLANGUAGE. Этим определяются соглашения по именам идентификаторов, порядок аргументов в стеке и то, останутся ли аргументы в стеке при возврате управления из процедуры (см. директиву MODEL). Если язык не задан, то используется язык заданный в директиве MODEL.
расстояние - это значения NEAR или FAR. Оно определяет тип инструкций RET или RETF, которые будут использоваться в процедуре.
аргумент - параметр процедуры в формате имя[:тип], где имя - имя параметра, тип - тип параметра. В качестве параметра можно задать массив в виде имя[N]:тип. Параметры будут доступны в процедуре через положительные смещения относительно регистра BP. Компилятор автоматически преобразует обращения к параметру по имени в соответствующие смещения относительно BP.
Директива ENDP
Определяет окончание процедуры
Директива USES
Показывает, какие регистры или элементы данных, состоящие из одной лексемы, вы хотите занести в стек в начале охватывающей процедуры. Перед возвратом управления из процедуры эти регистры будут извлекаться из стека. Вы должны использовать эту директиву перед первой инструкцией, которая генерирует в процедуре реальный код.
Директива LOCAL
В процедуре директива LOCAL определяет имена, которые доступны в стеке через отрицательные смещения относительно регистра BP. Если указан идентификатор, то ему присваивается количество байт, выделенных на локальные переменные (размер всего блока локальных переменных в байтах).
Пример кода:
.386 .model small, stdcall .stack 100h .code test proc Param1:word, Param2[3]:word uses ax, bx local LocVar:word = @size mov ax, @size mov ax, LocVar mov ax, Param1 mov ax, Param2[2] ret test endp start: mov ax, 4C00h int 21h end start
Директивы для макроопределений
Директива MACRO
Определяет начало макроопределения с указанным именем. У макроопредения могут быть заданы необязательные параметры, которые будут использоваться при подстановке тела макроопределения в текст программы.
При использовании макроопределения в программе, в параметры можно передавать строковые выражения, которые будут подставляться в тело макроопределения. Если передаваемая строка содержит пробелы или какие-то символы, вроде запятых, точек, то параметр можно заключить в угловые скобки <...>.
Пример кода:
.386 .model small, stdcall .stack 100h .data var dw 0 .code MAddr macro sreg,reg,addr mov reg, seg addr mov sreg,reg mov reg, offset addr endm start: MAddr ds,di,var mov ax, 4C00h int 21h end start
Директива ENDM
Определяет окончание макроопределения
Директива REPT
Повторяет блок операторов, заданный между директивами REPT и ENDM столько раз, сколько задается выражением. Блок операторов должен заканчиваться директивой ENDM.
Директива IRP
Повторяет блок операторов, заданный между директивой IRP и ENDM со строковой подстановкой. Аргументами может быть любой текст: символы, строки, числа и т.д. Для каждого указанного аргумента ассемблирование блока операторов выполняется только один раз. При каждом ассемблировании блока для каждого вхождения "параметра" в операторах подставляется следующий аргумент в списке.
Пример кода:
irp reg,ax,bx push reg endm ; после ассемблирования получится следующий код push ax push bx
Другие директивы
Директива COMMENT
Позволяет задать многострочный комментарий, ограниченный с начала и с конца заданным символом-ограничителем.
Пример кода:
comment * Несколько строк комментария *
Директива EQU
Определяет имя как строку, псевдоним или число, содержащие результат вычисления выражения.
Пример кода:
var equ 4000h mov ax, var ; то же самое, что mov ax,4000h
Директива END
Отмечает конец исполняемого модуля и задает начальный адрес, с которого будет исполняться программа.
Директива EVEN
Округляет счетчик адреса до следующего четного адреса
Директива SEG
Возвращается адрес сегмента выражения со ссылкой на память
Директива OFFSET
Возвращает смещение выражения в текущем сегменте (или в группе, которой принадлежит сегмент, если используются упрощенные директивы определения сегментов).
Директива ORG
Устанавливает счетчик инструкций в текущем сегменте в соответствии с адресом, задаваемым выражением.
Директива RADIX
Задает основание системы счисления для целочисленных констант (2, 8, 10 или 16)
Директива SIZE
Возвращает размер элемента данных, выделенного для переменной
Пример кода:
.data var dw 4 dup(0) .code mov ax,size var ;ax = 8
Комментарии (0)