Счетчик адреса отслеживает при ассемблировании исходного файла текущий адрес. Это позволяет вам в любой момент в процессе ассемблирования программа знать, где вы находитесь. Турбо Ассемб- лер предоставляет директивы, которые позволяют работать со счет- чиком адреса и помещать в него нужно значение адреса. Метки представляют собой имена, использующиеся для ссылок на адреса в программе. Меткам во время их определения присваивается текущее значение счетчика адреса программы. Метки позволяют вам назначать имена переменным в памяти и адресам конкретных инструк- ций. В данной главе описываются имеющиеся директивы, которые ис- пользуются для работы со счетчиком адреса и описания метод по те- кущему адресу.Идентификатор счетчика адреса $
Предопределенный идентификатор $ представляет текущий счет- чик адреса. Счетчик адреса состоит из двух частей: сегмента и смещения. При ассемблировании счетчик адреса представляет собой смещение в текущем сегменте. Счетчик адреса - это адрес адрес, который увеличивается и отражает текущий адрес при ассемблировании каждого оператора ис- ходного файла. Например: helpkMessage DB 'это справочное сообщение программы' helpLength = $ - helpMessage Когда эти две строки ассемблируются, идентификатор helpLength равен длине справочного сообщения.Директивы счетчика адреса $
В Турбо Ассемблере предусмотрено несколько директив, уста- навливающий счетчик инструкций. Эти директивы описываются в сле- дующем разделе. Заметим, что все эти директивы работают как в ре- жиме MASM, так и в режиме Ideal.Директива ORG
Вы можете использовать директиву ORG, чтобы установить счетчик адреса в значение текущего сегмента. Директива ORG имеет следующий синтаксис: ORG выражение где "выражение" не может содержать никаких имен идентификаторов с опережающими ссылками. Оно может быть константой или смещением от идентификатора в текущем сегменте, либо смещением относительно текущего счетчика адреса. Перед данными или кодом, которые уже введены в сегмент, вы можете восстановить значение счетчика адреса. Это можно использо- вать для возврата назад и заполнения записей таблицы, значения которых не были известны во время определения таблицы. Используй- те этот метод с осторожностью: вы можете непреднамеренно что-либо затереть. Директиву ORG можно использовать для того, чтобы связать метку с конкретным адресом. Директива ORG может также использо- ваться для задания начального адреса файлов .COM. Приведем приме- ры ее использования: PROG SEGMENT ORG 100h ; начальное смещение файла .COM start: ; ; остальная часть программы .COM PROG ENDS end start Приведем другой пример: PROG SEGMENT ASSUME cs:PROG, ds:PROG, ss:PROG, es:NOTHING ORG 20h EnvPtr label word ; определить метку для доступа ; к слову в PSP, которое ука- ; зывает на сегмент, содержа- ; щий блок операционной среды ; (он обычно освобождается для ; создания более компактной ; резидентной программы) ORG 80h CmdLength lebel byte ; определить метку для доступа ; к длине командной строки ORG @1h CmdLine label byte ; определить метку для доступа ; к тексту командной строки ORG 0100h start: ; освободить блок операционной среды mov es, EnvPtr ; ES -> блок операционной среды mov ah, 49h ; функция 49h: освободить блок ; памяти int 21h ; вызвать MS-DOS jc error_ENV ; ошибка освобождения EnvBlock? ; анализ командной строки mov al, CmdLength ; длина командной строки or al,al ; проверка на 0 jz no_params ; нет параметров mov cl,al ; поместить длину в cl mov ch,0 mov si,offset CmdLine ; адрес командной строки mov al,' ' ; символ для поиска repne scasb ; поиск первого пробела ; ; остальная часть файла .COM резидентной программы: PROG ENDS end startДирективы EVEN и EVENDATA
Вы можете использовать директиву EVEN для округления счетчи- ка адреса до следующего четного адреса. Директива EVEN позволяет вам выравнивать код для эффективного доступа к процессорам, ис- пользующим 16-разрядную шину данных. Производительность процессо- ров, использующих 8-разрядную шину данных, директивой EVEN не улучшается. Директива EVENDATA выполняет выравнивание на четную границу, изменяя счетчика адреса без генерации данных, что полезно исполь- зовать для неинициализированных сегментов. Директивы EVEN и EVENDATA приводят к тому, что если выравнивание текущего сегмента выполнено недостаточно строго, Турбо Ассемблер выводит предупреж- дающее сообщение. Если когда встречается директива EVEN счетчик адреса имеет нечетное значение, то Турбо Ассемблер помещает в сегмент один байт или инструкцию NOP, чтобы счетчик адреса стал четным. С по- мощью заполнения инструкциями NOP директиву EVEN можно в сегмен- тах кода, не вызывая на этапе работы программы выполнения невер- ных инструкций. Если счетчик адреса уже имеет четное значение, то данная директива не действует. Аналогично, если счетчик адреса имеет нечетное значение, когда встречается директива EVENDATA, Турбо Ассемблер генерирует неинициализированный байт. Приведем следующий пример использования директивы EVEN: EVEN @@A: lodsb xor bl,al ; выравнивание для эффективного доступа loop @@a Приведем пример использования директивы EVENDATA: EVENDATA VAR1 DW 0 ; выравнивание для эффективного ; доступа 8086Директива ALIGN
Для выравнивания счетчика адреса на адрес, значение которо- го равно степени 2, можно использовать директиву ALIGN. Директива ALIGN имеет следующий синтаксис: ALIGN граница где "граница" должна быть степенью 2. Если счетчик адреса еще не соответствует смещению, которое представляет собой произведение "границы", Турбо Ассемблер, чтобы присвоить счетчика адреса нужный адрес, вставляет в сегмент инс- трукции NOP (нет операции). Вы не можете выполнить надежное выравнивание на границу, яв- ляющееся более строгим, чем выравнивание сегмента, в котором встречается директива ALIGN. Выравнивание сегмента задается, ког- да сегмент в первый раз начинается по директива SEGMENT. Например, если вы определили сегмент следующим образом: CODE SEGMENT PARA PUBLIC затем вы можете задать ALIGN 16 (что эквивалентно PARA), но не ALIGN 32, как как это более строгое выравнивание, чем выравнива- ние, заданное в директиве SEGMENT с помощью PARA. Если выравнива- ние сегменте недостаточно строгое, то директива ALIGN генерирует предупреждающее сообщение. Использование директивы ALIGN показано в следующем примере: ALIGN 4 ; выравнивание на границу DWORD для 386 BignNum DD 12345678Определение меток
Метки позволяют вам присваивать значения идентификаторам. Существует три способа определения меток: - использование операции :; - использование директивы LABEL; - использование операции :: (MASM 5.1).Операция :
Операция : определяет ближнюю метку кода и имеет синтаксис: имя: где "имя" - это идентификатор, который вы не объявляли ранее в исходном коде. Ближние метки кода вы можете размещать на строке кода, где содержится только одна метка, или в начале строки перед инструкцией. Обычно ближние метки кода используются в качестве адреса перехода в инструкциях JMP и CALL в том же сегменте. Если вы не используете директиву PUBLIC, чтобы метка была доступна из других файлов, она доступна только в текущем исходном файле. Данная директива работает точно также, как при использовании директивы LABEL для определения ближней метки (NEAR). Например, A: эквивалентно A LABEL NEAR. Приведем пример использования операции : jne A ; пропустить следующую инструкцию inc si A: ; jne передает управление сюдаДиректива LABEL
Директиву LABEL вы можете использовать для определения иден- тификатора заданного типа. Заметим, что синтаксис в режимах MASM и Ideal различен. В режиме Ideal задавайте: LABEL имя сложный_тип В режиме MASM используйте следующее: имя LABEL сложный_тип где "имя" - это идентификатор, который вы не определяли ранее в исходном файле. "Сложный_тип" описывает размер идентификатора и то, ссылается он на код или данные. См. Главу 5, в которой можно найти дальнейшую информацию о сложных типах. Если вы не используете директиву PUBLIC, чтобы метка была доступна из других файлов, она доступна только в текущем исходном файле. Вы можете использовать директиву LABEL для доступа к элемен- там различного размера, которые содержатся в структуре данных. Этот принцип иллюстрируется следующим примером: WORDS LABEL WORD ; доступ к "BYTES" как к ; WORDS BYTES DB 64 DUP (0) mov WORDS[2],1 ; запись в WORDS 1Директива ::
Директива :: позволяет вам определить с областью действия, выходящей за рамки процедуры, в которой она находится. Это отли- чается от директивы : тем, что метки, определенные с помощью : имеют область действия только в текущей процедуре. Заметим, что :: отличается от : только когда вы задаете язык в операторе .MODEL. Приведем пример (файл DBLCOLON.ASM): VERSION M510 .MODEL SMALL,C .CODE A PROC NOP ASINGLE:NOP ADOUBLE::NOP NOP A ENDP B PROC NOP JMP ASINGLE ; приведет к ошибке JMP ADOUBLE RET B ENDP END
Назад | Содержание | Вперед