небольшое различие при использовании константы и смещения. Например,
с помощью команды
MOV DX,8[DI][4] ;Смещение+индекс+константа
в регистр DX пересылается элемент, взятый по абсолютному адресу в
регистре DS, смещению 8, относительному адресу в регистре DI и
константе 4.
Эти операнды можно комбинировать в любой последовательности. Но
нельзя использовать одновременно два базовых регистра [BX + BP] или два
индексных регистра [DI + SI]. Обычно индексированные адреса используются
для локализации элементов данных в таблицах.
ОПЕРАТОРЫ ЯЗЫКА АССЕМБЛЕР
________________________________________________________________
Существует три типа ассемблерных операторов: операторы атрибута,
операторы, возвращающие значение, и операторы. специфицирующие битовую
строку. В данном разделе рассмотрены первые два типа операторов.
Операторы, специфицирующие битовую строку, оператор MASK, счетчик сдвига и
оператор WIDTH относятся к директиве RECORD и будет рассмотрены в
следующем разделе.
Оператор LENGTH
-----------------
Оператор LENGTH возвращает число элементов, определенных операндом
DUP. Например, следующая команда MOV заносит в регистр DX значение 10:
TABLEA DW 10 DUP(?)
...
MOV DX,LENGTH TABLEA
Если операнд DUP отсутствует, то оператор LENGTH возвращает значение
01. См. операторы SIZE и TYPE в этом разделе.
Оператор OFFSET
------------------
Оператор OFFSET возвращает относительный адрес переменной или метки
внутри сегмента данных или кода. Оператор имеет следующий формат:
OFFSET переменная или метка
Например, команда
MOV DX,OFFSET TABLEA
устанавливает в регистре DX относительный адрес (смещение) поля TABLEA в
сегменте данных. (Заметим, что команда LEA выполняет аналогичное действие,
но без использования оператора OFFSET.)
Оператор PTR
---------------
Оператор PTR используется совместно с атрибутами типа BYTE, WORD или
DWORD для локальной отмены определенных типов (DB, DW или DD) или с
атрибутами NEAR или FAR для отмены значения дистанции по умолчанию. Формат
оператора следующий:
тип PTR выражение
В поле "тип" указывается новый атрибут, например BYTE. Выражение имеет
ссылку на переменную или константу. Приведем несколько примеров оператора
PTR:
FLDB DB 22H
DB 35H
FLDW DW 2672H ;0бьектный код 7226
MOV AН,BYTE PTR FLDW ;Пересылает 1-й байт (72)
ADD BL,BYTE PTR FLDW+1 ;Прибавляет 2-й байт (26)
MOV BYTE PTR FLDW,05 ;Пересылает 05 в 1-й байт
MOV AX,WORD PTR FLDB ;3аносит в АХ байты (2235)
CALL FAR PTR[BX] ;Длинный вызов процедуры
Директива LABEL, описанная в следующем разделе, выполняет функцию,
аналогичную оператору PTR.
Оператор SEG
--------------
Оператор SEG возвращает адрес сегмента, в котором расположена
указанная переменная или метка. Наиболее подходящим является использование
этого оператора в программах, состоящих из нескольких отдельно
ассемблируемых сегментов. Формат оператора:
SEG переменная или метка
Примеры применения оператора SEG в командах MOV:
MOV DX,SEG FLOW ;Адрес сегмента данных
MOV DX,SEG A20 ;Адрес сегмента кода
Оператор SHORT
----------------
Назначение оператора SHORT - модификация атрибута NEAR в команде JMP,
если переход не превышает границы +127 и -128 байт:
JMP SHORT метка
В результате ассемблер сокращает машинный код операнда от двух до
одного байта. Эта возможность оказывается полезной для коротких переходов
вперед, так как в этом случае ассемблер не может сам определить расстояние
до адреса перехода и резервирует два байта при отсутствии оператора SHORT.
Оператор SIZE
---------------
Оператор SIZE возвращает произведение длины LENGTH и типа TYPE и
полезен только при ссылках на переменную с операндом DUP. Формат
оператора:
SIZE переменная
См. пример для оператора TYPE.
Оператор TYPE
---------------
Оператор TYPE возвращает число байтов, соответствующее определению
указанной переменной:
Определение Число байтов
DB 1
DW 2
DD 4
DQ 8
DT 10
STRUC Число байтов, определённых в STRUC
NEAR метка FFFF
FAR метка FFFE
Формат оператора TYPE:
TYPE переменная или метка
Ниже приведены примеры, иллюстрирующие применение операторов TYPE, LENGTH
и SIZE:
FLDB DB ?
TABLEA DW 20 DUP(?) ;Определение 20 слов
...
MOV AX,TYPE FLDB ;AX = 0001
MOV AX,TYPE TABLEA ;AX = 0002
MOV CX,LENGTH TABLEA ;CX = 000A (10)
MOV DX,SIZE TABLEA ;DX = 0014 (20)
Так как область TABLEA определена как DW, то оператор TYPE возвращает
0002Н, LENGTH - 000АН (соответственно операнду DUP) и SIZE - произведение
типа и длины, т.е. 14Н (20).
ДИРЕКТИВЫ АССЕМБЛЕРА
________________________________________________________________
В данном разделе описано большинство ассемблерных директив. В гл.5
были подробно рассмотрены директивы для определения данных (DB, DW и
проч.).
Директива ASSUME
------------------
Назначение директивы ASSUME - установить для ассемблера связь между
сегментами и сегментными регистрами CS, DS, ES и SS. Формат директивы:
ASSUME сегментный_регистр:имя [, ... ]
В директиве указываются имена сегментных регистров, групп (GROUP) и
выражений SEG. Одна директива ASSUME может назначить до четырех сегментных
регистров в любой последовательности, например:
ASSUME CS:CODESG,DS:DATASG,SS:STACK,ES:DATASG
Для отмены любого ранее назначенного в директиве ASSUME сегментного
регистра необходимо использовать ключевое слово NOTHING:
ASSUME ES:NOTHING
Если, например, регистр DS оказался не назначен или отменен ключевым
словом NOTHING, то для ссылки к элементу из сегмента данных в командах
используется операнд со ссылкой к регистру DS:
MOV AX,DS:[BX] ;Использование индексного адреса
MOV AX,DS:FLDW ;Пересылка содержимого поля FLDW
Конечно, регистр DS должен содержать правильное значение сегментного
адреса.
Директива EXTRN
-----------------
Назначение директивы EXTRN - информировать ассемблер о переменных и
метках, которые определены в других модулях, но имеют ссылки из данного
модуля. Формат директивы:
EXTRN имя: тип [, ... ]
Директива EXTRN подробно рассмотрена в гл.21.
Директива GROUP
-----------------
Программа может содержать несколько сегментов одного типа (код,
данные, стек). Назначение директивы GROUP - собрать однотипные сегменты
под одно имя так, чтобы они поместились в один сегмент объемом 64 Кбайт,
формат директивы:
имя GROUP имя сегмента [, ... ]
Следующая директива GROUP объединяет SEG1 и SEG2 в одном ассемблерном
модуле:
GROUPX GROUP SEG1,SEG2
SEG1 SEGMENT PARA 'CODE'
ASSUME CS:GROUPX
SEG1 ENDS
SEG2 SEGMENT PARA 'CODE'
ASSUME CS:GROUPX
SEG2 ENDS
Директива INCLUDE
-------------------
Отдельные фрагменты ассемблерного кода или макрокоманды могут
использоваться в различных программах. Для этого такие фрагменты и
макрокоманды записываются в отдельные дисковые файлы, доступные для
использования из любых программ. Пусть некоторая подпрограмма,
преобразующая ASCII-код в двоичное представление, записана на диске С в
файле по имени CONVERT.LIB. Для доступа к этому файлу необходимо указать
директиву
INCLUDE C:CONVERT.LIB
причем в том месте исходной программы, где должна быть закодирована
подпрограмма преобразования ASCII-кода. В результате ассемблер найдет
необходимый файл на диске и вставит его содержимое в исходную программу.
(Если файл не будет найден, то ассемблер выдаст соответствующее сообщение
об ошибке и директива INCLUDE будет игнорирована.)
Для каждой вставленной строки ассемблер выводит в LST-файл в 30-й
колонке символ С (исходный текст в LST-файле начинается с 33-й колонки).
В гл.20 (Макрокоманды) дан практический пример директивы INCLUDE и
дано объяснение, каким образом можно использовать эту директиву только в
первом проходе ассемблера.
Директива LABEL
-----------------
Директива LABEL позволяет переопределять атрибут определенного имени.
Формат директивы:
имя LABEL тип
В качестве типа можно использовать BYTE, WORD или DWORD для
переопределения областей данных или имен структур или битовых строк.
Директивой LABEL можно переопределить выполнимый код, как NEAR или FAR.
Эта директива позволяет, например, определить некоторое поле и как DB, и
как DW. Ниже проиллюстрировано использование типов BYTE и WORD:
REDEFB LABEL BYTE
FIELDW DW 2532H
REDEFW LABEL WORD
FIELDB DB 25H
DB 32H
MOV AL,REDEFB ;Пересылка первого байта
MOV BX,REDEFW ;Пересылка двух байтов
Первая команда MOV пересылает только первый байт поля FIELDW. Вторая
команда MOV пересылает два байта, начинающихся по адресу FIELDB. Оператор
PTR выполняет аналогичные действия.
Директива NAME
----------------
Директива NAME обеспечивает другой способ назначения имени модулю:
NAME имя
Ассемблер выбирает имя модуля в следующем порядке:
1) если директива NAME присутствует, то ее операнд становится
именем модуля;
2) если директива NAME отсутствует, то ассемблер использует
первые шесть символов из директивы TITLE;
3) если обе директивы NAME и TITLE отсутствуют, то именем модуля
становится имя исходного файла.
Выбранное имя передается ассемблером в компоновщик.
Директива ORG
---------------
Для определения относительной позиции в сегменте данных или кода
ассемблер использует адресный счетчик. Рассмотрим сегмент данных со
следующими определениями:
Смещение Имя Операция Операнд Адресный счетчик