Группа директив для указания типа процессора

Директивы указания типа процессора задают набор используемых инструкций.

.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 SEGMENT [align] [combine] [use] ['class']

Определяет сегмент с заданным именем 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

ENDS

Определяет конец сегмента.

Директива ASSUME

ASSUME register:segment[,register:segment][, register:segment]...

Задает сегментный регистр, который будет использоваться для вычисления действующего адреса для всех меток и переменных, определенных для сегмента или группы сегментов с указанным именем.

Пример кода:

	.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

.MODEL memory-model [, language-type] [, stack-option]

Задает модель памяти  для  упрощенных  директив  определения сегментов.

Параметры:

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

.CODE [имя]

Определяет начало сегмента кода. Если задали среднюю или большую модель памяти, то за  директивой может следовать необязательное имя, которое указывает имя сегмента. По-умолчанию имя сегмента _TEXT.

Директива .DATA или DATASEG

.DATA

Определяет начало инициализированного сегмента данных.

Директива .DATA?

.DATA?

Определяет в модуле начало неинициализированного сегмента данных.

Директива .CONST

.CONST

Определяет начало сегмента данных-констант.

Сегменты .DATA, .DATA?, .CONST помещаются в одну группу с именем DGROUP

Директива .STACK или 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, DFDPDQ, DT - Резервирование памяти с размером соответственно 1 байт (DB), 2 байта (DW), 4 байта (DD), 6 байт (DF, DP), 8 байт (DQ) и 10 байт (DT)

[имя] DB выражение[, выражение][, выражение]...

Резервирует область памяти, заданного директивой размера, с указанным именем, и инициализирует значением выражения. Выражение может быть числом, строкой символов, специальным символом "?", а также выражением с использованием директивы DUP.

счетчик 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)

[имя] STRUC

Определяет структуру данных с заданным именем, содержащую поля. В каждом поле для определения его размера используются обычные директивы выделения данных (DB,  DW и т.д.). Поля структуры могут быть именованными или нет.

Директива ENDS

[имя] ENDS

Определяет конец структуры.

Пример кода:

str1	struc
	db	10h
field1	dw	?
field2	db	5 dup(?)
str1	ends

Директива UNION

[имя] 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

имя PROC [язык] [расстояние] [, аргумент] [, аргумент] ...

Определяет начало процедуры с указанным именем.

Необязательные параметры:

язык - определяет, из какого языка выполняется вызов для доступа к данной процедуре: C, PASCAL, BASIC, STDCALL или NOLANGUAGE. Этим определяются соглашения по именам идентификаторов, порядок аргументов в стеке и то, останутся ли аргументы в стеке при возврате управления из процедуры (см. директиву MODEL). Если язык не задан, то используется язык заданный в директиве MODEL.

расстояние - это значения NEAR или FAR. Оно определяет тип инструкций RET или RETF, которые будут использоваться в процедуре.

аргумент - параметр процедуры в формате имя[:тип], где имя - имя параметра, тип - тип параметра. В качестве параметра можно задать массив в виде имя[N]:тип. Параметры будут доступны в процедуре через положительные смещения относительно регистра BP. Компилятор автоматически преобразует обращения к параметру по имени в соответствующие смещения относительно BP.

Директива ENDP

[имя] ENDP

Определяет окончание процедуры

Директива USES

USES элемент[, элемент]...

Показывает, какие регистры или элементы данных, состоящие из одной лексемы, вы хотите занести в стек в начале охватывающей процедуры. Перед возвратом управления из процедуры эти регистры будут извлекаться из стека. Вы должны использовать эту директиву перед первой инструкцией, которая генерирует в процедуре реальный код.

Директива LOCAL

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

имя 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

ENDM

Определяет окончание макроопределения

Директива REPT

REPT выражение

Повторяет блок операторов, заданный между директивами REPT и ENDM столько раз, сколько задается выражением. Блок операторов должен заканчиваться директивой ENDM.

Директива IRP

IRP параметр, аргумент[. аргумент]...

Повторяет блок операторов, заданный между директивой IRP и ENDM со строковой подстановкой. Аргументами может быть любой текст: символы, строки, числа и т.д. Для каждого указанного аргумента ассемблирование блока операторов выполняется только один раз. При каждом ассемблировании блока для каждого вхождения "параметра" в операторах подставляется следующий аргумент в списке.

Пример кода:

	irp	reg,ax,bx
	push	reg
	endm
	; после ассемблирования получится следующий код
	push	ax
	push	bx

 

Другие директивы

Директива COMMENT

COMMENT [символ ограничитель] ... [символ ограничитель]

Позволяет задать многострочный комментарий, ограниченный с начала и с конца заданным символом-ограничителем.

Пример кода:

comment *
  Несколько
  строк
  комментария
*

Директива EQU

имя EQU выражение

Определяет имя как строку, псевдоним или число, содержащие результат вычисления выражения.

Пример кода:

var	equ	4000h
mov	ax, var	; то же самое, что mov ax,4000h

Директива END

END метка

Отмечает конец исполняемого модуля и задает начальный адрес, с которого будет исполняться программа.

Директива EVEN

EVEN

Округляет счетчик адреса до следующего четного адреса

Директива SEG

SEG выражение

Возвращается адрес сегмента выражения со ссылкой на память

Директива OFFSET

OFFSET выражение

Возвращает смещение выражения в текущем сегменте (или в группе, которой принадлежит сегмент, если используются упрощенные директивы определения сегментов).

Директива ORG

ORG выражение

Устанавливает счетчик инструкций в текущем сегменте в соответствии с адресом, задаваемым выражением.

Директива RADIX

RADIX основание

Задает основание системы счисления для целочисленных констант (2, 8, 10 или 16)

Директива SIZE

SIZE имя

Возвращает размер элемента данных, выделенного для переменной

Пример кода:

	.data
var	dw	4 dup(0)
	.code
	mov	ax,size var	;ax = 8