 |
ния сегментов. Вам они потребуются только для больших или специ-
альных программ, поэтому мы только кратко упомянем их. За более
подробной информацией вы можете обратиться к Главе 9.
Директива .DATA? используется аналогично директиве .DATA, но
она определяет ту часть сегмента данных, которая содержит неини-
циализированные данные. Она обычно используется в модулях Ассемб-
лера, которые компонуются с языком высокого уровня.
Директива .FARDATA позволяет вам определить дальний сегмент
данных, то есть сегмент данных, отличный от стандартного сегмента
@data, разделяемого (совместно используемого) всеми модулями. Ди-
ректива .FARDATA позволяет в модуле Ассемблера определить свои
собственные сегменты размером до 64К. Если задана директива
.FARDATA, то именем определенного по этой директиве дальнего сег-
мента данных будет @fardata, так же как @data - имя сегмента, оп-
ределенного по директиве .DATA.
Директива .FARDATA? во многом аналогична директиве .FARDATA,
но она определяет неинициализированный сегмент дальнего типа. Так
же как и для директивы .FARDATA и имени @fardata, при указании
директивы .FARDATA? сегмент данных дальнего типа, определенный по
этой директиве, получает имя @fardata?.
Директива .CONST определяет ту часть сегмента данных, в ко-
торой содержатся константы. Опять-таки это имеет силу только при
компоновке кода Ассемблера с языком высокого уровня.
При использовании упрощенных директив определения сегментов
можно использовать некоторые предопределенные метки. Метка
@FileName представляет собой имя ассемблируемого файла, @curseg -
имя сегмента, в который Турбо Ассемблер в данный момент выполняет
ассемблирование, @CodeSize - это 0 для моделей памяти с ближними
сегментами кода (сверхмалой, малой и компактная), 1 - для ком-
пактной и большой модели памяти и 2 - для сверхбольшой модели.
Аналогично, @DataSize = 0 в модели памяти с сегментами данных
ближнего типа (сверхмалая, малая и средняя модель памяти), 1 в
компактной и большой моделях и 2 - для сверхбольшой модели.
Стандартные директивы определения сегментов
-----------------------------------------------------------------
Далее мы приведем такой же пример программы, как и в преды-
дущем разделе, но на этот раз используем стандартные директивы
определения сегментов SEGMENT, ENDS и ASSUME.
DGROUP GROUP _DATA, STACK
ASSUME CS:_TEXT, DS:_DATA, SS:STACK
STACK SEGMENT PARA STACK 'STACK'
DB 200h DUP (?)
STACK ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
MemVar DW 0
.
.
.
_DATA ENDS
_TEXT SEGMENT WORD PUBLIC 'CODE'
ProgramStart:
mov ax,_DATA
mov ds,ax
mov ax,[MemVar]
.
.
.
mov ah,4ch
int 21h
_TEXT ENDS
END ProgramStart
Теперь вы видите, почему упрощенные директивы определения
сегментов называются упрощенными. Однако, многое из того, что де-
лают упрощенные директивы определения сегментов предназначено для
того, чтобы облегчить компоновку модулей Ассемблера с языками вы-
сокого уровня, что является излишним в автономных программах на
Ассемблере. Приведем пример программы HELLO с использованием
стандартных директив определения сегментов:
Stack Segment PARA STACK 'STACK'
DB 200h DUP (?)
Stack ENDS
Data SEGMENT WORD 'DATA'
HelloMessage DB 'Привет!',13,10,'$'
Data ENDS
Code Segment WORD 'CODE'
ASSUME CS:Code, DS:Data
ProgramStart:
mov ax,Data
mov ds,ax ; установить DS в значение
; сегмента данных
mov dx,OFFSET HelloMessage ; DS:DX указывает
; на сообщение 'Привет!'
mov ah,9 ; функция DOS вывода строки
int 21h ; вывести строку на экран
mov ah,4ch ; функция DOS завершения
; программы
int 21h ; завершить программу
Code ENDS
END ProgramStart
Последний пример не слишком усложнился, но тем не менее яс-
но, что стандартные директивы определения сегментов более сложны,
чем упрощенные директивы.
В Главе 9 стандартные (полные) директивы определения сегмен-
тов описываются более подробно. В данном разделе разделе мы пы-
таемся только дать вам представление о том, что делают стандарт-
ные директивы определения сегментов.
Директива SEGMENT
-----------------------------------------------------------------
Директива SEGMENT определяет начало сегмента. Метка, которая
указывается в данной директиве, определяет начало сегмента. Нап-
ример, директива:
Cseg SEGMENT
определяет начало сегмента с именем Cseg. Директива SEGMENT может
также (необязательно) определять атрибуты сегмента, включая вы-
равнивание в памяти на границу байта, слова, двойного слова, па-
раграфа (16 байт) или страницы (256 байт). Другие атрибуты вклю-
чают в себя способ, с помощью которого сегмент будет комбиниро-
ваться с другими сегментами с тем же именем и классом сегмента.
Директива ENDS
-----------------------------------------------------------------
Директива ENDS определяет конец сегмента. Например:
Cseg ENDS
завершает сегмент с именем Cseg, который начинался по директиве
SEGMENT. При использовании стандартных директив определения сег-
ментов вы должны явным образом завершать каждый сегмент.
Директива ASSUME
-----------------------------------------------------------------
Директива ASSUME указывает Турбо Ассемблеру, что в значение
какого сегмента установлен данный сегментный регистр. Директиву
ASSUME CS: требуется указывать в каждой программе, в которой ис-
пользуются стандартные сегментные директивы, так как Турбо Ас-
семблеру необходимо знать о сегменте кода для того, чтобы устано-
вить выполняемую программу. Кроме того, обычно используются
директивы ASSUME DS: и ASSUME ES:, благодаря которым Турбо Ас-
семблер знает, к каким ячейкам памяти вы можете адресоваться в
данный момент.
Директива ASSUME позволяет Турбо Ассемблеру проверить допус-
тимость каждого обращения к именованной ячейке памяти с учетом
значения текущего сегментного регистра. Рассмотрим следующий при-
мер:
.
.
.
Data1 SEGMENT WORD 'DATA'
Var1 DW 0
Data1 ENDS
.
.
.
Data2 SEGMENT WORD 'DATA'
Var2 DW 0
Data2 ENDS
Code SEGMENT WORD 'CODE'
ASSUME CS:Code
ProgramStart:
mov ax,Data1
mov ds,ax ; установить DS в Data1
ASSUME DS:Data1
mov ax,[Var2] ; попытаться загрузить Var2 в AX
; это приведет к ошибке, так как
; Var2 недоступна в сегменте
; Data1
.
.
.
mov ah,4ch ; номер функции DOS для
; завершения программы
int 21h ; завершить программу
Code ENDS
END ProgramStart
Турбо Ассемблер отмечает в данной программе ошибку, так как
в ней делается попытка получить доступ к переменной памяти Var2,
когда регистр DS установлен в значение сегмента Data1 (к Var2
нельзя адресоваться, пока DS не будет установлен в значение сег-
мента Data2).
Важно понимать, что Ассемблер на самом деле не знает, что
регистр DS установлен в значение Data1. С помощью директивы
|