- •Глава 1 Введение в семейство персональных компьютеров ibm pc
- •Глава 2 Выполнение программ
- •Глава 3 Требования языка ассемблер
- •Глава 4 Ассемблирование и выполнение программ
- •Глава 5 Определение данных
- •Глава 6 Программы в com-файлах
- •Глава 7 Логика и Организация Программы
- •Глава 8 Экранные операции I: Основные свойства
- •Глава 9 Экранные операции II: Расширенные возможности
- •Глава 10 Экранные операции III: Цвет и графика
- •Глава 11 Команды обработки строк
- •Глава 12 Арифметические операции I: Обработка двоичных данных
- •Глава 13 Арифметические операции II:
- •Глава 14 Обработка таблиц
- •Глава 15 Дисковая память I: Организация
- •Глава 16 Дисковая память II: Функции базовой версии dos
- •Глава 17 Дисковая память III: Расширенные функции dos
- •Глава 18 Дисковая память IV: Функции bios
- •Глава 19 Печать
- •Глава 20 Макросредства
- •Глава 21 Компоновка программ
- •Глава 22 Программный загрузчик
- •Глава 23 Прерывания bios и dos
- •Глава 24 Справочник по директивам языка Ассемблер
- •Глава 25 Справочник по командам языка Ассемблер
Глава 24 Справочник по директивам языка Ассемблер
__________________________________________________________________________
Ц е л ь: подробно описать операторы и директивы языка Ассемблер.
ВВЕДЕНИЕ
________________________________________________________________
Некоторые особенности Ассемблера кажутся на первый взгляд несколько
странными. Но после того, как вы ознакомились с простейшими и наиболее
общими свойствами Ассемблера, описанными в предыдущих главах, то
обнаружите, что описания в этой главе более понятны и являются удобным
руководством к программированию. В данной главе представлены операторы
атрибутов, операторы, возвращающие значение, директивы данных, а также
индексная адресация памяти.
ИНДЕКСНАЯ АДРЕСАЦИЯ ПАМЯТИ
________________________________________________________________
При прямой адресации памяти в одном из операндов команды указывается
имя определенной переменной, например для переменной COUNTER:
ADD CX,COUNTER
Во время выполнения программы процессор локализует указанную
переменную в памяти путем объединения величины смещения к этой переменной
с адресом сегмента данных.
При индексной адресации памяти ссылка на операнд определяется через
базовый или индексный регистр, константы, переменные смещения и простые
переменные. Квадратные скобки, определяющие операнды индексной адресации,
действуют как знак плюс (+). Для индексном адресации памяти можно
использовать:
- базовый регистр BX в виде [BX] вместе с сегментным регистром
DS или базовый регистр BP в виде [BP] вместе с сегментным регистром
SS. Например, с помощью команды
MOV DX,[BX] ;Базовый регистр
в регистр DX пересылается элемент, взятый по относительному адресу в
регистре BX и абсолютному адресу сегмента в регистре DS;
- индексный регистр DI в виде [DI] или индексный регистр SI в
виде [SI], оба вместе с сегментным регистром DS. Например, с помощью
команды
MOV AX,[SI] ;Индексный регистр
в регистр AХ пересылается элемент, взятый по относительному адресу в
регистре SI и абсолютному адресу сегмента в регистре DS;
- [константу], содержащую непосредственный номер или имя в
квадратных скобках. Например, с помощью команды
MOV [BX+SI+4],AX ;База+индекс+константа
содержимое регистра АХ пересылается по адресу, который вычисляется,
как сумма абсолютного адреса в регистре DS, относительного адреса в
регистре BX, относительного адреса в регистре SI и константы 4;
- смещение (+ или -) совместно с индексным операндом. Существует
небольшое различие при использовании константы и смещения. Например,
с помощью команды
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
---------------
Для определения относительной позиции в сегменте данных или кода
ассемблер использует адресный счетчик. Рассмотрим сегмент данных со
следующими определениями:
Смещение Имя Операция Операнд Адресный счетчик
00 FLDA DW 2542H 02
02 FLDB DB 36H 03
03 FLDC DW 212EH 05
05 FLDD DD 00000705H 09
Начальное значение адресного счетчика - 00. Так как поле FLDA
занимает два байта, то для получения адреса следующего элемента адресный
счетчик увеличивается до значения 02. Поле FLDB занимает один байт, значит
значение адресного счетчика увеличивается до значения 03 и т.д.. Для
изменения значения адресного счетчика и соответственно адреса следующего
определяемого элемента используется директива ORG. Формат директивы:
OR6 выражение
Выражение может быть абсолютным числом, но не символическим именем, и
должно формировать двухбайтовое абсолютное число. Рассмотрим следующие
элементы данных, определенные непосредственно после поля FLDD:
Смещение Имя Операция Операнд Адресный счетчик
ORG 0 00
00 FLDX DB ? 01
01 FLDY DW ? 02
03 FLDZ DB ? 04
ORG $+5 09
Первая директива ORG возвращает адресный счетчик в нулевое значение.
Поля FLDX, FLDY и FLDZ определяют те же области памяти, что и поля FLDA,
FLDB и FLDC:
Смещение: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| | | |
FLDA FLDB FLDC FLDD
| | |
FLDX FLDY FLDZ
Операнд, содержащий символ доллара ($), как во второй директиве ORG,
имеет текущее значение адресного счетчика. Таким образом, операнд $+5
устанавливает адресный счетчик равным 04 + 5 = 09, что представляет собой
то же значение, что и после определения поля FLDD.
Метка FLDC указывает на поле длиной в одно слово, находящееся по
смещению 03, а метка FLDZ указывает на однобайтовое поле по тому же
смещению:
MOV AX,FLOC ;Одно слово
MOV AL,FLDZ ;Oдин байт
Директиву ORG можно использовать для переопределения областей памяти.
При этом следует правильно устанавливать адресный счетчик и учитывать все
переопределяемые адреса памяти. Кроме того, новые переменные не должны
определять константы, так как при этом будут перекрыты константы,
определенные ранее. Директиву ORG нельзя использовать внутри определения
STRUCT.
Директива PROC
----------------
Любая процедура представляет собой совокупность кодов, начинающуюся
директивой PROC и завершающуюся директивой ENDP. Обычно эти директивы
используются для подпрограмм в кодовом сегменте. Ассемблер допускает
переход на процедуру с помощью команды JMP, но обычной практикой является
использование команды CALL для вызова процедуры и RET для выхода из
процедуры.
Процедура, находящаяся в одном сегменте с вызывающей процедурой,
имеет тип NEAR:
имя-процедуры PROC [NEAR]
Если операнд опущен, то ассемблер принимает значение NEAR no умолчанию.
Если процедура является внешней по отношению к вызывающему сегменту, то ее
вызов может осуществляться только командой CALL, а сама процедура должна
быть объявлена как PUBLIC. Более того, если в вызываемой процедуре
используется другое значение ASSUME CS, то необходимо кодировать атрибут
FAR:
PUBLIC имя-процедуры,
имя-процедуры PROC FAR
При вызове любой процедуры с помощью команды CALL необходимо
обеспечить возврат по команде RET.
Директива PUBLIC
------------------
Назначение директивы PUBLIC - информировать ассемблер, что на указанные
имена имеются ссылки из других ассемблерных модулей. Формат директивы:
PUBLIC имя [,...]
Директива PUBLIC подробно описана в гл.21.
Директива RECORD
------------------
Директива RECORD позволяет определять битовые строки. Одно из
назначений этой директивы - определить однобитовые или многобитовые
переключатели. Формат директивы:
имя RECORD имя-поля:ширина [=выражение] [, ... ]
Имя директивы и имена полей могут быть любыми уникальными
идентификаторами. После каждого имени поля следует двоеточие (:) и размер
поля в битах, которое может быть от 1 до 16 бит:
Число определенных битов Принимаемый размер
1...8 8
9...16 16
Любой размер поля до 8 бит представляется восемью битами, а от 9 до
16 бит - представляется шестнадцатью битами, выровненными справа (если
необходимо). Рассмотрим следующую директиву RECORD:
BITREC RECORD BIT1:3,BIT2:7,BIT3:6
Имя BIT1 определяет первые 3 бит поля BITREC, BIT2 - следующие 7 бит и
BIT3 - последние 6 бит. Общее число битов - 16, т.е. одно слово. Можно
инициализировать поле BITREC, например, следующим образом:
BITREC2 RECORD BIT1:3=101B,BIT2:7=0110110B,BIT3:011010B
Предположим, что директива RECORD находится перед сегментом данных.
Тогда внутри сегмента данных должен быть другой оператор, который отводит
память под данные. Для этого необходимо определить уникальное имя, имя
директивы RECORD и операнд, состоящий из угловых скобок (символы меньше и
больше):
DEFBITS BITREC <>
Данное определение генерирует объектный код AD9A. который записывается как
9AAD в сегмент данных. В угловых скобках может находиться значение,
переопределяющее BITREC.
Программа на рис.24.1 иллюстрирует определение BITREC директивой
RECORD, но без начальных значений. В этом случае соответствующий оператор
в сегменте данных инициализирует каждое поле операндом в угловых скобках.
Дополнительно к директиве RECORD имеются операторы WIDTH, MASK и
фактор сдвига. Использование этих операторов позволяет изменять
определение директивы RECORD без изменения команд, которые имеют ссылки на
директиву RECORD.
О п е р а т о р WIDTH. Оператор WIDTH возвращает число битов в
директиве RECORD или в одном из ее полей. На рис.24.1 после метки А10
имеется два примера оператора WIDTH. Первая команда MOV загружает в
регистр BH число битов во всем поле RECORD BITREC (16 бит); вторая команда
MOV загружает в регистр AL число битов в поле BIT2 (7 бит). В обоих
случаях ассемблер генерирует для числа битов непосредственный операнд.
__________________________________________________________________________
TITLE RECORD (COM) Проверка директивы RECORD
0000 CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
0100 ORG 100H
0100 EB 02 BEGIN: JMP SHORT MAIN
; -----------------------------------------------------
BITREC RECORD BIT1:3,BIT2:7,BIT3:6 ;Определить запись
0102 9A AD DEFBITS BITREC <101B,0110110B,011010B> ;Инициализировать биты
; -----------------------------------------------------
0104 MAIN PROC NEAR
0104 A10: ;Ширина:
0104 B7 10 MOV BH,WIDTH BITREC ; записи (16)
0106 B0 07 MOV AL,WIDTH BIT2 ; поля (07)
0108 B10: ;Величина сдвига:
0108 B1 0D MOV CL,BIT1 ; шест.0D
010A B1 06 MOV CL,BIT2 ; 06
010C B1 00 MOV CL,BIT3 ; 00
010E C10: ;Маска:
010E B8 E000 MOV AX,MASK BIT1 ; шест.E000
0111 BB 1FC0 MOV BX,MASK BIT2 ; 1FC0
0114 B9 003F MOV CX,MASK BIT3 ; 003F
0117 D10: ;Выделение BIT2:
0117 A1 0102 R MOV AX,DEFBITS ; получить запись,
011A 25 1FC0 AND AX,MASK BIT2 ; очистить BIT1 и BIT3,
011D B1 06 MOV CL,BIT2 ; получить сдвиг 06,
011F D3 E8 SHR AX,CL ; сдвинуть вправо
0121 E10: ;Выделение BIT1:
0121 A1 0102 R MOV AX,DEFBITS ; получить запись,
0124 B1 0D MOV CL,BIT1 ; получить сдвиг 13,
0126 D3 E8 SHR AX,CL ; сдвинуть вправо
0128 C3 RET
0129 MAIN ENDP
0129 CODESG ENDS
END BEGIN
_____________________________________________________________________
Structures and records:
N a m e Widht # fields
Shift Widht Mask Initial
BITREC . . . . . . . . . . . 0010 0003
BIT1 . . . . . . . . . . . . 000D 0003 E000 0000
BIT2 . . . . . . . . . . . . . 0006 0007 1FC0 0000
BIT3 . . . . . . . . . . . . 0000 0006 003F 0000
Segments and Groups:
N a m e Size Align Combine Class
CODESG . . . . . . . . . . . . 0129 PARA NONE 'CODE'
Symbols:
N a m e Type Value Attr
A10. . . . . . . . . . . . . . L NEAR 0104 CODESG
B10. . . . . . . . . . . . . . L NEAR 0108 CODESG
BEGIN. . . . . . . . . . . . . L NEAR 0100 CODESG
C10. . . . . . . . . . . . . . L NEAR 010E CODESG
D10. . . . . . . . . . . . . . L NEAR 0117 CODESG
DEFBITS. . . . . . . . . . . . L WORD 0102 CODESG
E10. . . . . . . . . . . . . . L NEAR 0121 CODESG
MAIN . . . . . . . . . . . . . N PROC 0104 CODESG Length =0025
__________________________________________________________________________
Рис.24.1. Использование диpективы RECORD
Ф а к т о р с д в и г а. Прямая ссылка на элемент в RECORD,например:
MOV CL,BIT2
в действительности не имеет отношения к содержимому BIT2. Вместо этого
ассемблер генерирует непосредственный операнд, который содержит "фактор
сдвига", помогающий изолировать необходимое поле. Непосредственное
значение представляет собой число, на которое необходимо сдвинуть BIT2 для
выравнивания справа. На рис.24.1 после метки В10 имеются три команды,
которые загружают в регистр CL фактор сдвига для полей BIT1, BIT2 и BITЗ.
О п е р а т о р MASK. Оператор MASK возвращает "маску" из единичных
битовых значений, которые представляют специфицированное поле, иными
словами, определяют битовые позиции, которые занимает поле. Например,
оператор MASK для каждого из полей, определенных в области BITREC,
возвращает следующие значения:
Поле Двоичное значение Шестнадцатиричное значение
В1Т1 1110000000000000 Е000
В1Т2 0001111111000000 1FC0
В1ТЗ 0000000000111111 003F
На рис.24.1 три команды после метки С10 загружают в регистры значения
оператора MASK для полей BIT1, BIT2 и BITЗ. Команды после меток D10 и Е10
иллюстрируют выделение значений полей BIТ2 и BIТ1 соответственно из
области BITREC. После метки D10 в регистр АХ загружается все значение
области, определенной директивой RECORD, а затем из этого значения с
помощью оператора MASK выделяются только биты поля BIТ2:
Область RECORD: 101 0110110 011010
AND MASK BIТ2: 000 1111111 000000
Результат: 000 0110110 000000
В результате сбрасываются все биты, кроме принадлежащих к полю BIТ2.
Следующие две команды приводят к сдвигу содержимого регистра АХ на шесть
битов для выравнивания справа:
0000000000110110 (0036Н)
После метки Е10 в регистр AХ загружается все значение области,
определенной директивой RECORD, и так как BIТ1 является самым левым полем,
то в примере используется только фактор для сдвига значения вправо на 13
бит:
0000000000000101 (0005Н)
Директива SEGMENT
-------------------
Ассемблерный модуль может состоять из одного или более сегментов,
части сегмента или даже частей нескольких сегментов. Формат директивы:
имя_сегмента SEGMENT [выравнивание] [объединение] [класс]
.
.
.
имя_сегмента ENDS
Все операнды являются необязательными. Ниже описаны операнды для
выравнивания, объединения и указания класса.
В ы р а в н и в а н и е. Операнд выравнивания определяет начальную
границу сегмента, например
PAGE = xxx00
PARA = хххх0 (граница по умолчанию)
WORD = ххххe (четная граница)
BYTE = ххххх
где х - любая шестнадцатиричная цифра,
е - четная шестнадцатиричная цифра.
О б ъ е д и н е н и е. Операнд объединения указывает способ обработки
сегмента, при компоновке:
NONE: Значение по умолчанию. Сегмент должен быть логически отделен от
других сегментов, хотя физически он может быть смежным.
Предполагается, что сегмент имеет собственный базовый адрес;
PUBLIC: Все PUBLIC - сегменты, имеющие одинаковое имя и класс,
загружаются компоновщиком в смежные области. Все такие сегменты имеют
один общий базовый адрес;
STACK: Для компоновщика операнд STACK аналогичен операнду PUBLIC. В
любой компонуемой программе должен быть определен по крайней мере
один сегмент STACK. Если объявлено более одного стека, то стековый
указатель (SP) устанавливается на начало первого стека;
COMMON: Для сегментов COMMON с одинаковыми именами и классами
компоновщик устанавливает один общий базовый адрес. При выполнении
происходит наложение второго сегмента на первый. Размер общей области
определяется самым длинным сегментом;
AT-параграф: Параграф должен быть определен предварительно. Данный
операнд обеспечивает определение меток и переменных по фиксированным
адресам в фиксированных областях памяти, таких, как ROM или таблица
векторов прерываний в младших адресах памяти. Например, для
определения адреса дисплейного видеобуфера используется
VIDEO_RAM SEGMENT AT 0B800H
Класс: Операнд класс может содержать любое правильное имя,
заключенное в одиночные кавычки. Данный операнд используется
компоновщиком для обработки сегментов, имеющих одинаковые имена и
классы. Типичными примерами являются классы 'STACK' и 'CODE'.
Следующие два сегмента объединяются компоновщиком в один физический
сегмент при одном значении сегментного регистра:
--------------------------------
Ассемблерный SEG1 SEGMENT PARA PUBLIC 'CODE'
модуль 1 ASSUME CS:SEG1
...
SEG1 ENDS
--------------------------------
Ассемблерный SEG2 SEGMENT PARA PUBLIC 'CODE'
модуль 2 ASSUME CS:SEG1
...
SEG2 ENDS
--------------------------------
Сегменты могут быть вложенными один в другой:
SEG1 SEGMENT
... Начало SEG1
SEG2 SEGMENT
... Область SEG2
SEG2 ENDS
... Конец SEG1
SEG1 ENDS
Для объединения сегментов в группы используйте директиву GROUP.
Директива STRUC
-----------------
Директива STRUC обеспечивает определение различных полей в виде
структуры. Данная директива не поддерживается в малом ассемблере ASM.
Формат директивы:
Имя-структуры STRUC
...
[определение полей данных]
...
Имя-структуры ENDS
Структура начинается собственным именем в директиве STRUC и
завершается таким же именем в директиве ENDS. Ассемблер записывает поля;
определенные в структуре, одно за другим от начала структуры. Правильными
операторами определения полей являются DB, DW, DD и DT с указанием имен
или без них.
На рис.24.2 директива STRUC определяет список параметров PARLIST для
ввода имени с клавиатуры. Следующий далее оператор выделяет память под
данную структуру:
PARAMS PARLIST <>
Данный оператор обеспечивает адресацию структуры внутри программы. Угловые
скобки (символы меньше и больше) в данном случае пусты, но в них можно
указать данные для переопределения областей внутри структуры.
В командах ассемблера может использоваться прямая адресация по имени
структуры. Для ссылки на определенное поле внутри структуры в командах
используется имя структуры (PARAMS в данном примере) и через точку имя
конкретного поля:
MOV AL,PARAMS.ACTLEN
Используя оператор выделения памяти, можно переопределить содержимое
полей внутри структуры. Правила для практического использования этой
возможности можно найти в руководстве по Ассемблеру.
__________________________________________________________________________
TITLE DSTRUC (COM) Определение структуры
0000 CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
0100 ORG 100H
0100 EB 29 BEGIN: JMP SHORT MAIN
; ---------------------------------------------
PARLIST STRUC ;Список параметров
0000 19 MAXLEN DB 25 ;
0001 ?? ACTLEN DB ? ;
0002 19 [ 20 ] NAMEIN DB 25 DUP(' ') ;
001B PARLIST ENDS
;
0102 19 PARAMS PARLIST <> ;Область структуры
0103 ??
0104 19 [ 20 ]
011D 57 68 61 74 20 69 PROMPT DB 'What is name?', 'S'
73 20 6E 61 6D 65
3F 24
; ---------------------------------------------
012B MAIN PROC NEAR
012B B4 09 MOV AH,09 ;Выдать запрос
012D 8D 16 011D R LEA DX,PROMPT
0131 CD 21 INT 21H
0133 B4 0A MOV AH,0AH ;Получить ввод
0135 8D 16 0102 R LEA DX,PARAMS
0139 CD 21 INT 21H
013B A0 0103 R MOV AL,PARAMS.ACTLEN ;Длина ввода
; ...
013E C3 RET
013F MAIN ENDP
013F CODESG ENDS
END BEGIN
Structures and records:
N a m e Width # fields
Shift Width Masc Initial
PARLIST. . . . . . . . . . . . . 001B 0003
MAXLEN . . . . . . . . . . . . 0000
ACTLEN . . . . . . . . . . . . 0001
NAMEIN . . . . . . . . . . . . 0002
Segments and Groups:
N a m e Size Align Combine Class
CODESG . . . . . . . . . . . . . 013F PARA NONE 'CODE'
Symbols:
N a m e Type Value Attr
BEGIN. . . . . . . . . . . . . L NEAR 0100 CODESG
MAIN . . . . . . . . . . . . . N PROC 012B CODESG Length =0014
PARAMS . . . . . . . . . . . . L 001B 0102 CODESG
PROMPT . . . . . . . . . . . . L BYTE 011D CODESG
__________________________________________________________________________
Рис.24.2. Пpимеp опpеделения стpуктуpы