CodeNet / Языки программирования / Ассемблер / СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
Директива 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. С помощью директивы
ASSUME вы указали Турбо Ассемблеру, что нужно сделать такое допу-
щение. Директива ASSUME дает вам способ в любой момент сообщить
Ассемблеру о значении сегментного регистра, после чего Турбо Ас-
семблер будет сообщать вам, если вы пытаетесь сделать невозмож-
ное.
Однако Турбо Ассемблер не может перехватывать все подобные
ошибки. Когда в ссылке на память используется именованная пере-
менная памяти (такая, как Var1 и Var2 в предыдущем примере), Тур-
бо Ассемблер может проверить допустимость этой ссылки, так как
каждая именованная переменная памяти явным образом связана с сег-
ментом. Невозможно сообщить Турбо Ассемблеру, к какому сегменту
пытается обратиться инструкция:
mov al,[bx]
В этом случае Турбо Ассемблер должен предположить, что зна-
чение сегментного регистра DS соответствует тому сегменту, к ко-
торому вы хотите обратиться.
Если в данный момент сегментный регистр не указывает ни на
какой именованный сегмент, то чтобы сообщить об этом Ассемблеру,
можно использовать в директиве ASSUME ключевое слово NOTHING.
Например:
.
.
.
mov ax,0b800h
mov ds,ax
ASSUME ds:NOTHING
.
.
.
Здесь регистр DS устанавливается таким образом, чтобы указы-
вать на цветной графический экран, а затем Турбо Ассемблеру сооб-
щается, что регистр DS не указывает ни на какой именованный сег-
мент. Вот еще один способ ссылки на цветной графический экран:
.
.
.
ColorTextSeg SEGMENT AT 0B8000h
ColorTextMemory LABEL BYTE
ColorTextSeg ENDS
.
.
.
mov ax,ColorTextSeg
mov ds,ax
ASSUME ds:ColorTextSeg
.
.
.
Обратите внимание, что в директиве AT, которая следует за
директивой SEGMENT, задается явный начальный адрес сегмента.
Сделаем последнее замечание по директиве 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,Data2
mov es,ax ; установить ES в Data2
ASSUME ES:Data2
mov ax,[Var2] ; загрузить Var2 в AX -
; Турбо Ассемблер укажет
; процессору 8086, что
; загрузку нужно выполнять
; относительно ES, так как
; к Var2 нельзя получить
; доступ относительно DS
.
.
.
mov ah,4ch ; функция DOS завершения
; работы программы
int 21h ; завершить программу
Code ENDS
END ProgramStart
Данный пример должен быть вам знаком: это модифицированная
версия фрагмента программы, использованного нами ранее для того,
чтобы показать, как директива ASSUME позволяет Турбо Ассемблеру
указать вам, когда вы пытаетесь использовать недопустимую ссылку
на память. Однако в данном примере сообщение об ошибке не выво-
дится. Но это не означает, что Турбо Ассемблер позволяет вам сде-
лать ошибку. Он модифицирует инструкцию:
mov ax,[Var2]
для доступа к Var2 относительно сегментного регистра ES, а не
сегментного регистра DS.
Это происходит по следующим причинам. Две директивы ASSUME
информируют Турбо Ассемблер о том, что регистр DS установлен в
значение сегмента Data1, а ES установлен в значение сегмента
Data2. Турбо Ассемблер совершенно правильно заключает, что к Var2
нельзя получить доступ относительно регистра DS, однако Var2 дос-
тупно относительно сегментного регистра ES. В итоге Турбо Ассем-
блер включает перед инструкцией MOV специальный код (префикс пе-
реопределения сегмента), чтобы указать процессору 8086, что вмес-
то сегментного регистра DS нужно использовать сегментный регистр
ES.
Какое все это имеет для вас значение? Это значит, что если
вы корректно используете директивы ASSUME, позволяя Турбо Ассем-
блеру узнать о текущих установленных для регистров DS и ES значе-
ниях, то он может автоматически вам помочь, проверяя возможность
доступа к именованным переменным в памяти и в некоторых случаях
даже может выполнить автоматическую корректировку сегмента.
Общее обсуждение префиксов переопределения сегментов и стан-
дартные директивы определения сегментов обсуждаются в Главе 10.
