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, а затем из этого значения с