Знаковые и беззнаковые данные
Рассматривая назначение команд условного перехода следует пояснить характер их использования. Типы данных, над которыми выполняются арифметические операции и операции сравнения определяют какими командами пользоваться: беззнаковыми или знаковыми. Беззнаковые данные используют все биты как биты данных; характерным примером являются символьные строки: имена, адреса и натуральные числа. В знаковых данных самый левый бит представляет собой знак, причем если его значение равно нулю, то число положительное, и если единице, то отрицательное. Многие числовые значения могут быть как положительными так и отрицательными.
В качестве примера предположим, что регистр AX содержит 11000110, а BX — 00010110. Команда:
CMP AX,BX
сравнивает содержимое регистров AX и BX. В случае, если данные беззнаковые, то значение в AX больше, а если знаковые — то меньше.
Запомните, что для беззнаковых данных есть переходы по состояниям равно, выше или ниже, а для беззнаковых — равно, больше или меньше. Переходы по проверкам флагов переноса, переполнения и паритета имеют особое назначение. Ассемблер транслирует мнемонические коды в объектный код независимо от того, какую из двух команд вы применили.
Процедуры и оператор CALL
Ранее примеры содержали в кодовом сегменте только oдну процедуру, оформленную следующим образом:
BEGIN PROC FAR
.
.
BEGIN ENDP
Операнд FAR информирует систему о том, что данный адрес является точкой входа для выполнения, а директива ENDP определяет конец процедуры.
Кодовый сегмент, однако, может содержать любое количество процедур, которые разделяются директивами PROC и ENDP.
Обратите внимание на следующие особенности:
uДирективы PROC по меткам имеют операнд NEAR для указания того, что эти процедуры находятся в текущем кодовом сегменте.
uКаждая процедура имеет уникальное имя и содержит собственную директиву ENDP для указания конца процедуры.
uДля передачи управления в процедуре BEGIN имеются две команды: CALL. В результате первой команды CALL управление передается указанной процедуре и начинается ее выполнение. Достигнув команды RET, управление возвращается на команду непосредственно следующую за первой командой CALL. Вторая команда CALL действует аналогично — передает управление в указанную процедуру, выполняет ее команды и возвращает управление по команде RET.
uКоманда RET всегда выполняет возврат в вызывающую программу.
Программа BEGIN вызывает процедуры, которые возвращают управление обратно в BEGIN. Для выполнения самой программы BEGIN операционная система DOS вызывает ее и в конце выполнения команда RET возвращает управление в DOS. В случае, если процедура не содержит завершающей команды RET, то выполнение команд продолжится непосредственно в этой процедуре. В случае, если процедура не содержит команды RET, то будут выполняться команды, оказавшиеся за процедурой с непредсказуемым результатом.
Использование процедур дает хорошую возможность организовать логическую структуру программы. Кроме того, операнды для команды CALL могут иметь значения, выходящие за границу от -128 до +127 байт.
Технически управление в процедуру типа NEAR может быть передано с помощью команд перехода или даже обычным построчным кодированием. Но в большинстве случаев рекомендуется использовать команду CALL для передачи управления в процедуру и команду RET для возврата.
Сегмент стека
Ниже буду рассмотрены только две команды, использующие стек, — это команды PUSH в начале сегмента кодов, которые обеспечивают возврат в DOS, когда EXE-программа завершается.
Естественно для этих программ требуется стек oчень малого размера. Однако, команда CALL автоматически записывает в стек относительный адрес команды, следующей непосредственно за командой CALL, и увеличивает после этого указатель вершины стека. В вызываемой процедуре команда RET использует этот адрес для возврата в вызывающую процедуру и при этом автоматически уменьшается указатель вершины стека.
Таким образом, команды PUSH записывают в стек двухбайтовые адреса или другие значения. Команды POP обычно выбирают из стека записанные в него слова. Эти операции изменяют относительный адрес в регистре SP (то есть, в указатели стека) для доступа к следующему слову. Данное свойство стека требует чтобы команды RET и CALL соответствовали друг другу. Кроме того, вызванная процедура может вызвать с помощью команды CALL другую процедуру, а та в свою очередь — следующую. Стек должен иметь достаточные размеры для того, чтобы хранить все записываемые в него адреса. Как правило, стек объемом в 32 слова является достаточным.
Команды PUSH, PUSHF, CALL, INT, и INTO заносят в стек адрес возврата или содержимое флагового регистра. Команды POP, POPF, RET и IRET извлекают эти aдреса или флаги из стека.
При передаче управления в EXE-программу система устанавливает в регистрах следующие значения:
DS и ES
Адрес префикса программного сегмента — область в 256 (шест. 100) байт, которая предшествует выполняемому программному модулю в памяти.
CS
Адрес точки входа в программу (адрес первой выполняемой команды).
IP
Нуль.
SS
Адрес сегмента стека.