ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.


Rtl-sdr приемник.

 

Часть 4

3.4.5 Команды установки байта по условию
----------------------------------------------------------------
Эта группа команд устанавливает значение байта равным нулю или
единице в зависимости от любого из 16 условий, определяемых
флагами статуса. Байт может находиться как в регистре, так и в
памяти. Эти команды особенно полезны для поддержки Булевских
выражений в языках программирования высокого уровня, таких, как
Паскаль.
Некоторые языки представляют логическую единицу как целое, в
котором все биты установлены. Это может быть сделано при помощи
команды SETcc с взаимно исключающими условиями и последующим
уменьшением результата на единицу.
SETcc (Установить значение байта в зависимости от условия cc)
загружает значение 1 в байт, если условие cc истинно, в
противном случае очищает байт. Смотри Приложение D для
определения всех возможных условий.
3.4.6 Команда проверки
----------------------------------------------------------------
TEST (Проверить) выполняет логическое "and" для двух операндов,
очищает флаги OF и CF, оставляя флаг AF неопределенным и
обновляя значения флагов SF, ZF и PF. Флаги могут быть проверены
командами условной передачи управления или командами установки
значения байта по условию. Операндами служат байты, слова или
двойные слова.
Разница между командами TEST и AND заключается в том, что
команда TEST не изменяет значение операнда назначения. Разница
между командами TEST и BT заключается в том, что TEST может
проверять значения множества битов за одну операцию, в то время
как команда BT проверяет один бит.
3.5 Команды передачи управления
----------------------------------------------------------------
Процессор i486 поддерживает команды как условной, так и
безусловной передачи управления для контроля за ходом выполнения
программы. Команды условной передачи управления выполняются
только для некоторых комбинаций состояния флагов. Команды
безусловной передачи управления выполняются всегда.
3.5.1 Команды безусловной передачи управления.
----------------------------------------------------------------
Команды  JMP, CALL, RET, INT и IRET передают выполнение адресату
в программном сегменте.  Адресат может находиться как в  том  же
программном сегменте (близкая передача), так и в другом
программном сегменте (дальняя передача). Форматы команд, которые
передают управление в другие сегменты, обсуждаются в следующем
разделе данной главы. Если модель организации памяти,
используемая в некоторой прикладной программе, не позволяет
программисту видеть другие сегменты, дальняя передача управления
использоваться не должна.
3.5.1.1 Команда перехода
----------------------------------------------------------------
JMP (Переход) безусловно передает управление адресату. Команда
JMP является однонаправленной командой передачи управления; она
не сохраняет адрес возврата в стеке.
Команда JMP передает управление из текущей процедуры в другую
процедуру. Адрес процедуры указывается непосредственно в
команде, в регистре или в ячейке памяти. Местоположение адреса
определяет, интерпретируется ли адрес как относительный адрес
или как абсолютный адрес.
Относительный  адрес.  Относительный переход использует смещение
(непосредственная константа, используемая при вычислении
адреса) заданное в команде. Смещение имеет знак и длину (байт
или двойное слово). Адрес назначения формируется путем сложения
смещения и адреса, хранящегося в регистре EIP. После этого в
регистре EIP будет содержаться адрес команды, которая должна
выполняться после команды перехода.
Абсолютный адрес. Абсолютный переход используется с 32-разрядным
смещением одним из следующих способов :
1. Программа может выполнять переход по адресу в регистре общего
   назначения. Это 32-разрядное значение копируется в регистр
   EIP и выполнение продолжается.
2. Адресат назначения может быть переменной в памяти, указанной
   с использованием сдандартного режима адресации. Операнд
   копируется в регистр EIP и выполнение продолжается.
3.5.1.2 Команды вызова процедур
----------------------------------------------------------------
CALL (Вызов процедуры) передает управление и сохраняет адрес
команды, следующей за командой CALL, для дальнейшего
использования командой RET (Возврат). CALL сохраняет текущее
содержимое регистра EIP в стеке. Команда RET в вызванной
процедуре использует этот адрес в стеке для передачи управления
назад в вызывающую программу.
Команды CALL и JMP имеют абсолютный и относительный форматы.
Косвенная команда CALL указывает абсолютный адрес одним из
следующих способов :
1. Программа может выполнить переход по адресу в регистре общего
   назначения. 32-разрядное значение копируется в регистр EIP,
   адрес возврата сохраняется в стеке и выполнение продолжается.
2. Адресат назначения может быть переменной в памяти, указанной
   с использованием стандартного режима адресации. Операнд
   копируется в регистр EIP, адрес возврата сохраняется в стеке
   и выполнение продолжается.
3.5.1.3 Команды возврата и возврата-из-прерывания
----------------------------------------------------------------
RET (Возврат из процедуры) завершает выполнение процедуры и
передает управление команде, следующей за командой CALL,
которая вызвала данную процедуру. Команда RET восстанавливает
содержимое регистра EIP, которое было сохранено в стеке при
вызове процедуры.
Команда RET имеет необязательный операнд непосредственного
значения. Когда операнд имеется, эта константа  прибавляется к
содержимому регистра ESP, что имеет эффект удаления всех
параметров, сохраненных в стеке перед вызовом процедуры.
IRET (Возврат из прерывания) возвращает управление прерванной
процедуре. Команда IRET отличается от команды RET тем, что она
восстанавливает содержимое регистра EFLAGS из стека. Содержимое
регистра EFLAGS запоминается в стеке при возникновении
прерывания.
3.5.2 Команды условной передачи управления
----------------------------------------------------------------
Команды условной передачи управления являются переходами,
которые передают управление, если состояния регистра EFLAGS
удоволетворяет условиям, заданным в команде.
3.5.2.1 Команды условного перехода.
----------------------------------------------------------------
В Таблице 3-3 приведена мнемоника команд перехода. Команды,
приведенные парами, являются альтернативными именами одной и той
же команды. Язык ассемблера поддерживает эти имена для большей
ясности листингов программ.
Разрешена форма команды условного перехода, которая использует
смещение, суммируемое с содержимым регистра EIP, если указанное
условие верно. Смещение может быть байтом или двойным словом.
Смещение имеет знак; оно может быть использовано для перехода
вперед и назад.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і             Условные переходы без знака                      і
ГДДДДДДДДДДДВДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і Мнемоника і  Статус флагов  і           Описание             і
ГДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і JA/JNBE   і (CF or ZF) = 0  і выше/не ниже не равно          і
і JAE/JNB   і CF = 0          і выше или равно/не ниже         і
і JB/JNAE   і CF = 1          і ниже/не выше не равно          і
і JBE/JNA   і (CF or ZF) = 1  і ниже или равно/не выше         і
і JC        і CF = 1          і перенос                        і
і JE/JZ     і ZF = 1          і равно/ноль                     і
і JNC       і CF = 0          і нет переноса                   і
і JNE/JNZ   і ZF = 0          і не равно/не ноль               і
і JNP/JPO   і PF = 0          і нет четности/нечетное          і
і JP/JPE    і PF = 1          і четность/четное                і
ГДДДДДДДДДДДБДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і             Условные переходы со знаком                      і
ГДДДДДДДДДДДВДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
і JG/JNLE   і((SF xor OF)     і больше/не меньше не равно      і
і           і  or ZF) = 0     і больше или равно/не меньше     і
і JGE/JNL   і (SF xor OF) = 0 і меньше/не больше не равно      і
і JL/JNGE   і (SF xor OF) = 1 і меньше или равно/не больше     і
і JLE/JNG   і((SF xor OF)     і нет переполнения               і
і           і  or ZF) = 1     і нет знака (неотрицательное)    і
і JNO       і OF = 0          і переполнение                   і
і JNS       і SF = 1          і знак (отрицательное)           і
і JO        і OF = 1          і                                і
і JS        і SF = 1          і                                і
АДДДДДДДДДДДБДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
         Таблица 3-3. Команды условного перехода.
3.5.2.2 Команды управления циклом
----------------------------------------------------------------
Команды управления циклом являются командами условного
перехода, которые используют значение, помещенное в регистр
ECX, в качестве счетчика числа выполнений тела цикла. Все
команды управления циклом уменьшают значение регистра ECX при
каждом выполнении цикла и завершают работу при достижении
значения ноль. Четыре из пяти команд управления циклом
воспринимают флаг ZF в качестве условия завершения цикла до
момента достижения счетчиком цикла значения ноль.
LOOP (Цикл до тех пор, пока ECX не равен нулю) является командой
условной передачи управления, которая уменьшает содержимое
регистра ECX перед проверкой условия завершения цикла. Если
содержимое регистра ECX отлично от нуля, программа передает
управление по адресу, указанному в команде в качестве адреса
назначения (преемника). Команда LOOP приводит к выполнению части
программы, которое повторяется до тех пор, пока счетчик не
станет равным нулю. Когда достигается значение нуля, выполнение
передается команде, следующей непосредственно за командой LOOP.
Если значение регистра ECX равняется нулю перед первым
выполнением цикла, счетчик цикла умеьшается на 1, регистру
присваивается значение 0FFFFFFFFH и цикл выполняется 2**32 раза.
LOOPE (Цикл до тех пор, пока равенство) и LOOPZ (Цикл до тех
пор, пока ноль) являются синонимами одной и той же команды. Эти
команды являются командами условного перехода, которые
уменьшают содержимое регистра ECX перед проверкой условия
завершения цикла. Если значение регистра ECX не равно нулю и
установлен флаг ZF, программа передает управление по адресу,
указанному в качестве операнда назначения в команде. Когда
достигнуто значение нуля или флаг ZF очищен, выполнение
передается команде, следующей непосредственно за командой LOOPE/
LOOPZ.
LOOPNE (Цикл до тех пор, пока неравенство) и LOOPNZ (Цикл до тех
пор, пока не ноль) являются синонимами одной и той же команды.
Эти команды являются командами условного перехода, которые
уменьшают содержимое регистра ECX перед проверкой условия
завершения цикла. Если значение регистра ECX не равно нулю и
очищен флаг ZF, программа передает управление по адресу,
указанному в качестве операнда назначения в команде. Когда
достигнуто значение нуля или флаг ZF установлен, выполнение
передается команде, следующей непосредственно за командой LOOPNE
/LOOPNZ.
3.5.2.3. Выполнение цикла или повтор ноль раз
----------------------------------------------------------------
JECXZ (Переход, если ECX равен нулю) переходит по адресу,
указанному в команде в качестве операнда назначения, если в
регистре ECX содержится значение ноль. Команда JECXZ
используется совместно с командой LOOP и с командами
сканирования строки и сравнения. Так как эти команды уменьшают
значение регистра ECX перед проверкой на ноль, цикл будет
выполняться 2**32 раза, если обращение к циклу произошло, когда
в регистре ECX содержалось значение ноль. Команда JECXZ
используется для создания циклов, которые пропускаются без
выполнения, если начальное значение равно нулю. Команда JECXZ в
начале цикла может быть использована для перехода за пределы
цикла, если значение счетчика цикла равняется нулю. Когда
команда используется вместе с повторяющимся командами
сканирования строки и сравнения, JECXZ может определить условие
окончания цикла до достижения счетчиком значения нуля или до
выполнения условий сканирования или сравнения.
3.5.3 Программные прерывания.
----------------------------------------------------------------
Команды INT, INTO и BOUND позволяют программисту осуществлять
передачу управления программе обработки прерываний или
исключениям.
INTn (Программное прерывание) вызывает программу обработки,
указанную вектором прерываний, заданным в команде. Команда INT
может задавать любые типы прерываний. Эта команда используется
для поддержки множества типов программных прерываний или для
проверки работы сервисных программ обработки прерываний.
Сервисные программы обработки прерываний завершаются командой
IRET, которая передает управление к команде, следующей за
командой INT.
INTO (Прерывание по переполнению) вызывает программу обработки
исключений по переполнению, если установлен флаг OF. Если
данный флаг очищен, выполнение продолжается без вызова
программы обработки. Флаг OF устанавливается арифметическими и
логическими командами и командами работы со строками. Команда
INTO поддерживает использование программных прерываний для
обработки ошибочных ситуаций, таких, как арифметическое
переполнение.
BOUND (Обнаружить выход значения за допустимые границы)
сравнивает значение со знаком, хранящееся в регистре общего
назначения, с верхним и нижним пределами. Программа обработки
исключений по контролю выхода за допустимые границы вызывается,
если значение, содержащееся в регистре, меньше чем нижняя
граница, или больше чем верхняя граница. Эта команда
поддерживает использование программных прерываний для контроля
выхода за допустимые границы, таких как проверка индекса
массива, чтобы убедиться в том, что он попадает в диапазон
границ, заданный для массива.
Команда BOUND имеет два операнда. Первый операнд указывает
регистр общего назначения, который необходимо проверить. Второй
операнд указывает базовый адрес двух слов или двух двойных слов,
расположенных по соседству в памяти. Нижней границей является
слово или двойное слово с младшим адресом, верхняя граница имеет
старший адрес. Команда BOUND предполагает, что верхнее граничное
значение и нижнее граничное значение расположены в смежных
ячейках памяти. Верхняя и нижняя граница не могут быть
операндами-регистрами; если же они таковыми являются, возникает
исключение по неверному коду операции.
Верхняя и нижняя границы массива могут располагаться в памяти
даже до самого массива. Это позволяет задавать границы массива
как постоянное смещение относительно начала массива. Так как
адрес массива уже должен находиться в регистре, такая практика
позволяет избежать дополнительных циклов шины для получения
эффективной адресации границ массива.
3.6 Команды работы со строками
----------------------------------------------------------------
Команды работы со строками работают с большими структурами
данных в памяти, такими, как алфавитно-цифровые строки символов.
Смотри также раздел, посвященный Вводу/Выводу, для получения
более подробной информации относительно команд Ввода/Вывода
строк (иногда их называют блочными командами Ввода/Вывода).
Работа со строками может выполняться посредством команд работы
со строками (которые выполняют только одну итерацию для каждой
операции) совместно с другими возможностями команд процессора,
такими, как префиксы повторения. Команды работы со строками :
MOVS - Переслать строку.
CMPS - Сравнить строки.
SCAS - Сканировать строку.
LODS - Загрузить строку.
STOC - Запомнить строку.
После выполнения команды работы со строкой, регистры
строки-источника и строки-преемника указывают на следуюшие
элементы в этих строках. Эти регистры автоматически увеличивают
или уменьшают свои значения на количество байт, занятых каждым
элементом строки. Элементом строки может быть байт, слово или
двойное слово. Строчными регистрами являются :
ESI - Регистр индекса источника.
EDI - Регистр индекса преемника.
Операции работы со строками могут начинаться со старших адресов
и выполняться по направлению к младшим адресам, или могут
начинаться с младших адресов и выполняться по направлению к
старшим адресам. Направление выполнения управляется флагом :
DF - Флаг направления.
Если флаг DF очищен, регистры увеличиваются. Если флаг
установлен, регистры уменьшаются. Следующие команды
устанавливают и очищают флаг :
STD - Команда установки флага направления.
CLD - Команда очистки флага направления.
Для того, чтобы выполнить операции более чем над одним элементом
строки, должны использоваться префиксы повторения, такие как:
REP - Повторять до тех пор, пока регистр ECX не равен нулю.
REPE/REPZ - Повторять до тех пор, пока регистр ECX не равен нулю
и установлен флаг ZF.
REPNE/REPNZ  -  Повторять  до тех пор, пока регистр ECX не равен
нулю и флаг ZF очищен.
Исключения и прерывания, которые могут возникать в процессе
выполнения команд работы со строками, сохраняют регистры в таком
состоянии, чтобы команда работы со строкой могла быть повторена.
Регистры источника и преемника указывают на следующие элементы
строк, регистр EIP указывает на команду работы со строкой и
регистр ECX содержит значение, сохраненное в нем со времени
последней успешной итерации. Все, что необходимо для повторного
запуска операции - это обработать прерывание или зафиксировать
источник исключения, затем выполнить команду IRET.
3.6.1 Префиксы повторения.
----------------------------------------------------------------
Префиксы повторения REP (Повторять, пока ECX не равен нулю),
REPE/REPZ (Повторять пока равно/ноль) и REPNE/REPNZ (Повторять
пока не равно/не ноль) задают повторяющееся выполнение команд
работы со строками. Эта форма итераций позволяет операциям
работы со строками работать быстрее, чем это возможно при
организации программных циклов.
Когда у команды работы со строкой имеется префикс повторения,
операция выполняется до тех пор, пока одно из условий окончания,
определяемое префиксом, не будет выполнено.
Для каждого повторения команды работа со строкой может быть
приостановлена прерыванием или исключением. После того, как
прерывание или исключение было обработано, операция работы над
строкой может быть продолжена с того места, на котором она была
приостановлена. Этот механизм позволяет выполнять длинные
операции над строками без влияния на время отклика системы на
прерывание.
Все три префикса, приведенные в Таблице 3-4, принуждают команду
выполняться до тех пор, пока значение регистра ECX не уменьшится
до нуля, если ни одно из других условия окончания работы не
будет выполнено. Префиксы повторения отличаются друг от друга по
своим дополнительным условиям окончания работы. Префикс REP не
имеет дополнительных условий окончания. Префиксы REPE/REPZ и
REPNE/REPNZ используются исключительно с командами SCAS
(Сканировать строку) и CMPS (Сравнить строки). Префикс REPE/REPZ
заканчивает работу, если флаг ZF очищен. Префикс REPNE/REPNZ
заканчивает работу, если флаг ZF установлен. Флаг ZF не требует
предварительной инициализации перед выполнением повторяющихся
команд работы со строками, так как и SCAS и CMPS воздействуют на
флаг ZF в соответствие с результатами сравнения, которое они
выполнили.
ЪДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДї
і Префикс повтора і Условие окончания 1 і Условие окончания 2 і
ГДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДґ
і  REP            і    ECX = 0          і    отсутствует      і
і  REPE/REPZ      і    ECX = 0          і    ZF = 0           і
і  REPNE/REPNZ    і    ECX = 0          і    ZF = 1           і
АДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДЩ
                 Таблица 3-4. Команды повтора.
3.6.2 Флаги управления индексированием и направлением
----------------------------------------------------------------
Хотя регистры общего назначения в большинстве случаев полностью
взаимозаменяемы, команды работы со строками требуют
использования двух специальных регистров. Строки источнока и
преемника находятся в памяти, адресуемой регистрами ESI и EDI.
Регистр ESI указывает на операнд-источник. По умолчанию, регистр
ESI используется вместе с сегментным регистром DS. Префикс
замены сегмента позволяет использовать регистр ESI вместе с
сегментными регистрами CS, SS, ES, FS или GS. Регистр EDI
указывает на операнд-преемник. Он использует сегмент, на который
указывает сегментный регистр ES; замена этого сегмента
запрещена. Использование двух различных сегментных регистров в
одной команде позволяет работать со строками, расположенными в
различных сегментах.
Когда в командах работы со строками используются регистры ESI и
EDI, они автоматически увеличиваются или уменьшаются после
каждой итерации. Действия над строками можно начинать выполнять
со старших адресов по направлению к младшим адресам, или они
могут выполняться, начиная с младших адресов по направлению к
старшим адресам. Направление операций управляется флагом DF.
Если флаг очищен, значения регистров увеличиваются. Если флаг
установлен, значения регистров уменьшаются. Команды STD и CLD
устанавливают и очищают этот флаг. Программисты всегда должны
поместить нужное значение во флаг DF, прежде чем использовать
команды работы со строками.
3.6.3 Команды работы со строками
----------------------------------------------------------------
MOVS (Переслать строку) перемещает элемент строки, адресуемый
регистром ESI в позицию, адрес которой указан в регистре EDI.
Команда MOVEB перемещает байты, команда MOVEW перемещает слова и
команда MOVED перемещает двойные слова. Команда MOVE, когда она
дополнена префиксом REP, работает как пересылка блоков из памяти
в память. Для выполнения этой операции программа должна
инициализировать регистры ECX, ESI и EDI. Регистр ECX указывает
количество элементов в блоке.
CMPS (Сравнение строк) вычитает элемент строки-преемника из
элемента строки-источника и обновляет флаги AF, SF, PF, CF и OF.
Ни один из элементов не будет записан обратно в память. Если
элементы строки равны, устанавлиавется флаг ZF; в противном
случае этот флаг очищается. CMPSB сравнивает байты, CMPSW
сравнивает слова и CMPSD сравнивает двойные слова.
SCAS (Сканировать строку) вычитает элемент строки-преемника из
регистра EAX, AX или AL (в зависимости от длины операнда) и
обновляет флаги AF, SF, ZF, PF и OF. Строка и регистры не
изменяются. Если значения равны, устанавливается флаг ZF; в
противном случае флаг очищается. Команда SCASB сканирует байты,
команда SCASW сканирует слова и команда SCASD сканирует двойные
слова.
Когда  префиксы  REPE/REPZ  или REPNE/REPNZ модифицируют команду
SCAS или CMPS, сформированный при этом цикл  заканчивается  либо
по  счетчику  цикла,  либо  по тому воздействию, которое команды
SCAS или CMPS оказывают на флаг ZF.
LODS (Загрузить строку) помещает элемент строки-источника, на
который указывает адрес в регистре ESI, в регистр EAX для строк
из двойных слов, в регистр AX для строк из слов или в регистр AL
для строк из байтов. Эта команда используется обычно внутри
цикла, где другие команды обрабатывают каждый элемент строки по
мере его появления в регистре.
STOS (Запомнить строку) помещает элемент строки из регистра EAX,
AX или AL в строку, на которую указывает адрес в регистре EDI.
Эта команда обычно используется в цикле, где она записывает в
память результат обработки элемента строки, считанного из памяти
при помощи команды LODS. Команда REP'STOS является самым быстрым
способом инициализации большого блока памяти.
3.7 Команды для языков с блочной структурой
----------------------------------------------------------------
Эти команды обеспечивают поддержку машинно-ориентированным
языком языков с блочной структурой, таких, как Cи или Паскаль.
Они включают в себя команды ENTER и LEAVE, которые упрощают вход
в процедуру и выход из нее в созданном компилятором коде. Они
поддерживают структуру указателей (пойнтеров) и локальных
переменных в стеке, называемую кадром стека.
ENTER (Вход в процедуру) создает кадр стека, совместимый с
контекстными правилами языков с блочной структурой. В этих
языках процедура имеет доступ к своим собственным переменным и
некоторому количеству других переменных, определенных где-либо
еще в программе. Контекстом процедуры называется множество
переменных, к которым процедура имеет доступ. Правила контекста
различны для разных языков; они могут основываться на
вложенности процедур, на делении программы на отдельно
скомпилированные файлы или на некоторых других схемах
подразделения на модули.
Команда ENTER имеет два операнда. Первый операнд указывает на
количество байт, которое должно быть зарезервированно в стеке
для динамического хранения данных в процедуре, в которую будет
осуществлен вход. Динамическим хранением называется память,
отведенная для переменных, создаваемых в тот момент, когда
процедура вызвана, известных также, как автоматические
переменные. Второй параметр является лексическим уровнем
вложенности (от 0 до 31) процедуры. Уровень вложенности - это
глубина процедуры в иерархии блочно-структурированной программы.
Лексический уровень не имеет никакого отношения ни к уровню
привилегированности защиты, ни к уровню привилегированности
Ввода/Вывода.
Лексический уровень вложенности определяет число указателей
кадров стека, которые надо скопировать в новый кадр стека из
предыдущего кадра. Указателем на кадр стека является двойное
слово, используемое для доступа к переменным процедуры.
Множество указателей на кадры стека, используемых процедурой для
доступа к переменным других процедур, называется отображением
(данных). Первое двойное слово в отображении является указателем
на предыдущий кадр стек. Этот указатель используется командой
LEAVЕ для аннулирования результата действий команды ENTER путем
отмены текущего кадра стека.
      Пример : ENTER 2048,3 .
Зарезервировать  2Кбайт динамической памяти в стеке и установить
указатели на два предыдущих кадра стека в кадре стека для этой
процедуры.
После того, как команда ENTER создаст отображение для процедуры,
она размещает динамические (автоматические) локальные переменные
для данной процедуры путем уменьшения содержимого регистра ESP
на количество байт, заданное в первом параметре. Это новое
значение регистра ESP служит в качестве начального значения
верхушки стека для всех операций PUSH и POP внутри процедуры.
Для того, чтобы позволить процедуре адресовать (обращаться) к
своему отображению, команда ENTER предоставляет регистру EBP
указывать на первое двойное слово в отображении. Так как стеки
увеличиваются вниз, это действительно двойное слово с самым
старшим адресом в отображении. Команды работы с данными, которые
указывают регистр EBP в качестве базового регистра,
автоматически адресуют позиции внутри сегмента стека вместо
сегмента данных.
Команда   ENTER   может  быть  использована  двумя  способами:
вложенным и не вложенным. Если лексический уровень равен 0,
используется не вложенная форма. Не вложенная форма сохраняет
содержимое регистра EBP в стеке, копирует содержимое регистра
ESP в регистр EBP и вычитает первый операнд из содержимого
регистра ESP, для того, чтобы разместить динамическую память.
Не вложенная форма отличается от вложенной тем, что не
копируются никакие указатели на кадры стека. Вложенная форма
команды ENTER появляется тогда, когда второй параметр
(лексический уровень) не равен нулю.
Рисунок 3-15 показывает определения форматов команды ENTER.
STORAGE - это количество байт динамической памяти для размещения
локальных переменных, и LEVEL - это лексический уровень
вложенности.
Главная процедура (в которую вложены  все  остальные  процедуры)
работает   на   самом  старшем  лексическом  уровне,  уровне  1.
Следующая процедура, которую она  вызывает,  работает  на  более
глубоком лексическом уровне, уровне 2.  Процедура уровня 2 может
получать  доступ  к  переменным   главной   процедуры,   которые
находятся  в  зафиксированном положении, указанном компилятором.
В случае уровня 1 команда ENTER резервирует  только  запрошенную
динамическую  память  в  стеке,  так  как нет никаких предыдущих
отображений, которые следовало бы скопировать.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і                                                              і
і                           Сохранить EBP                      і
і                           Установить временное значение      і
і                              FRAME_PTR равным ESP            і
і                           IF LEVEL = 0, то                   і
і                              Повторять (LEVEL - 1) раз       і
і                                  EBP := EBP -4               і
і                                Сохранить в стеке двойное     і
і                          слово, на которое указывает EBP     і
і                              Конец повтора                   і
і                              Восстановить FRAME_PTR          і
і                           END IF                             і
і                           EBP := FRAME_PTR                   і
і                           ESP := ESP - STORAGE               і
і                                                              і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
        Рисунок 3-15. Определение формата команды ENTER.
Процедура, которая вызывает другую процедуру на более низком
лексическом уровне, дает вызванной процедуре возможность доступа
к переменным вызвавшей ее процедуры. Команда ENTER обеспечивает
этот доступ путем размещения указателя на кадр стека вызывающей
процедуры в отображении.
Процедура, которая вызывает другую процедуру на том же
лексическом уровне, не дает возможности доступа к своим
переменным. В этом случае команда ENTER копирует только ту часть
отображения вызывающей процедуры, которая относится к предыдущим
вложенным процедурам, работающим на более высоких лексических
уровнях. Новый кадр стека не содержит указателя для адресации
кадра стека вызвавшей процедуры.
Команда ENTER интерпретирует реентерабельную процедуру как вызов
процедуры на том же лексическом уровне. В этом случае каждая
следующая итерация реентерабельной процедуры может адресоваться
только к своим собственным переменным и переменным процедур,
внутри которых она вложена. Реентерабельная процедура всегда
может адресовать свои собственные переменные; ей не требуется
для этого указателей на кадры стека предыдущих итераций.
Путем копирования только указателей на кадры стека процедур на
более высоких лексических уровнях команда ENTER добивается того,
что процедуры получают доступ только к переменным более высоких
лексических уровней, но не к переменным параллельных лексических
уровней (смотри Рисунок 3-16).
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і                                                             і
і                                                             і
і   ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї   і
і   і          ГЛАВНАЯ ПРОГРАММА (УРОВЕНЬ 1)              і   і
і   і  ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї  і   і
і   і  і           ПРОЦЕДУРА А (УРОВЕНЬ 2)             і  і   і
і   і  і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і  і   і
і   і  і і         ПРОЦЕДУРА B (УРОВЕНЬ 3)           і і  і   і
і   і  і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і  і   і
і   і  і                                               і  і   і
і   і  і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і  і   і
і   і  і і         ПРОЦЕДУРА C (УРОВЕНЬ 3)           і і  і   і
і   і  і і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї   і і  і   і
і   і  і і і       ПРОЦЕДУРА D (УРОВЕНЬ 4)       і   і і  і   і
і   і  і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ   і і  і   і
і   і  і і                                           і і  і   і
і   і  і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і  і   і
і   і  і                                               і  і   і
і   і  АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ  і   і
і   і                                                     і   і
і   і                                                     і   і
і   АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ   і
і                                                             і
і                                                             і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
               Рисунок 3-16. Вложенные процедуры.
Языки  программирования  с блочной структурой могут использовать
лексический уровень вложенности,  определенный  командой  ENTER,
для  управления  доступом  к  переменным вложенных процедур.  На
рисунке,  например,  если  ПРОЦЕДУРА  A  вызывает  ПРОЦЕДУРУ  B,
которая, в свою очередь, вызывает ПРОЦЕДУРУ C, тогда ПРОЦЕДУРА C
получит доступ к переменным ГЛАВНОЙ ПРОГРАММЫ и ПРОЦЕДУРЫ A,  но
не  к переменным ПРОЦЕДУРЫ C, так как они расположены ма одном и
том же  лексическом  уровне.   Следующее  определение  описывает
доступ к переменным для вложенных процедур на Рисунок  3-16 :
1. ГЛАВНАЯ ПРОГРАММА имеет переменные на фиксированных позициях.
2. ПРОЦЕДУРА A может получать доступ к переменным только ГЛАВНОЙ
   ПРОГРАММЫ.
3. ПРОЦЕДУРА B может получить доступ только к переменным
   ПРОЦЕДУРЫ A и ГЛАВНОЙ ПРОГРАММЫ. ПРОЦЕДУРА B не может
   получить доступ к переменным ПРОЦЕДУРЫ C или ПРОЦЕДУРЫ D.
4. ПРОЦЕДУРА C может получить доступ только к переменным
   ПРОЦЕДУРЫ A и ГЛАВНОЙ ПРОГРАММЫ. ПРОЦЕДУРА C не может
   получить доступ к переменным ПРОЦЕДУРЫ B или ПРОЦЕДУРЫ D.
5. ПРОЦЕДУРА D может получить доступ к переменным ПРОЦЕДУРЫ C,
   ПРОЦЕДУРЫ A и ГЛАВНОЙ ПРОЦЕДУРЫ. ПРОЦЕДУРА D не может
   получить доступ к переменным ПРОЦЕДУРЫ B.
На следующей диаграмме команда ENTER в начале ГЛАВНОЙ программы
создает три двойных слова динамической памяти для ГЛАВНОЙ
программы, но не копирует никаких указателей из других кадров
стека (смотри Рисунок 3-17). Первое двойное слово в отображении
содержит копию последнего значения регистра EBP перед тем, как
была выполнена команда ENTER. Второе двойное слово (которое, так
как стек растет вниз, хранится по младшему адресу) содержит
копию содержимого регистра EBP следом за выполнением команды
ENTER. После того, как команда была выполнена, регистр EBP
указывает на первое двойное слово, сохраненное в стеке, и
регистр ESP указывает на последнее двойное слово в кадре стека.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і                                                             і
і                                                             і
і                       ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДї        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   ЪДДДі         СТАРОЕ EBP         іДДEBP  і
і      ОТОБРАЖЕНИЕ  і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   АДДДі  EBP из ГЛАВНОЙ программы  і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   ЪДДДі                            і        і
і      ДИНАМИЧЕСКАЯ і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і      ПАМЯТЬ       і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   АДДДі                            іДДESP  і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       АДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ        і
і                                                             і
і                                                             і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
   Рисунок 3-17. Стек данных после запуска ГЛАВНОЙ программы.
Когда ГЛАВНАЯ программа вызывает ПРОЦЕДУРУ А, команда ENTER
создает новое отображение (смотри Рисунок 3-18). Первое двойное
слово - последнее значение, содержавшееся в регистре EBP ГЛАВНОЙ
программы. Второе двойное слово - указатель на кадр стека
ГЛАВНОЙ программы, который скопирован из второго двойного слова
отображения в ГЛАВНОЙ программе. Это слово в данной ситуации
является другой копией последнего значения, содержавшегося в
регистре EBP в ГЛАВНОЙ программе. ПРОЦЕДУРА А может получить
доступ к переменным ГЛАВНОЙ программы, так как ГЛАВНАЯ программа
находится на уровне 1. Более того, базовый адрес динамической
памяти, используемой в ГЛАВНОЙ программе, является текущим
адресом в регистре EBP плюс четыре байта дополнительно для
сохраненного содержимого регистра EBP в ГЛАВНОЙ программе. Все
динамические переменные для ГЛАВНОЙ программы находятся на
фиксированном положительном смещении относительно этого
значения.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і                                                             і
і                                                             і
і                       ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДї        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і         СТАРОЕ EBP         і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ГЛАВНОЙ программы  і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   ЪДДДі  EBP из ГЛАВНОЙ программы  іДДEBP  і
і                   і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і      ОТОБРАЖЕНИЕ  і   і  EBP из ГЛАВНОЙ программы  і        і
і                   і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   АДДДі  EBP из ПРОЦЕДУРЫ А        і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   ЪДДДі                            і        і
і      ДИНАМИЧЕСКАЯ і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і      ПАМЯТЬ       і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   АДДДі                            іДДESP  і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       АДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ        і
і                                                             і
і                                                             і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
      Рисунок 3-18. Стек данных после запуска ПРОЦЕДУРЫ А
Когда ПРОЦЕДУРА А вызывает ПРОЦЕДУРУ B, команда ENTER создает
новое отображение (смотри Рисунок 3-19). Первое двойное слово
содержит копию последнего значения регистра EBP в ПРОЦЕДУРЕ А.
Второе и третье двойные слова являются копиями двух указателей
на кадр стека в отображении в ПРОЦЕДУРЕ А. ПРОЦЕДУРА B может
получать доступ к переменным ПРОЦЕДУРЫ А и ГЛАВНОЙ программы
путем использования указателей на кадры стека в своем
отображении.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і                                                             і
і                                                             і
і                       ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДї        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і         СТАРОЕ EBP         і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ГЛАВНОЙ программы  і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ГЛАВНОЙ программы  і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ГЛАВНОЙ программы  і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ПРОЦЕДУРЫ А        і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   ЪДДДі  EBP из ПРОЦЕДУРЫ А        іДДEBP  і
і                   і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   і   і  EBP из ГЛАВНОЙ программы  і        і
і      ОТОБРАЖЕНИЕ  і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   і   і  EBP из ПРОЦЕДУРЫ А        і        і
і                   і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   АДДДі  EBP из ПРОЦЕДУРЫ B        і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   ЪДДДі                            і        і
і      ДИНАМИЧЕСКАЯ і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і      ПАМЯТЬ       і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   АДДДі                            іДДESP  і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       АДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ        і
і                                                             і
і                                                             і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
      Рисунок 3-19. Стек данных после запуска ПРОЦЕДУРЫ B
Когда ПРОЦЕДУРА B вызывает ПРОЦЕДУРУ С, команда ENTER создает
новое отображение для ПРОЦЕДУРЫ С (смотри Рисунок 3-20). Первое
двойное слово содержит копию последнего значения регистра EBP в
ПРОЦЕДУРЕ B. Оно будет использовано командой LEAVE для
восстановления кадра стека ПРОЦЕДУРЫ B. Второе и третье двойные
слова являются копиями указателей кадров стека в отображении
ПРОЦЕДУРЫ А. Если ПРОЦЕДУРА С находится на лексическом уровне
следующей глубины по отношению к ПРОЦЕДУРЕ B, четвертое двойное
слово будет скопировано, и оно будет указателем на кадр стека
для локальных переменных ПРОЦЕДУРЫ B.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і                                                             і
і                                                             і
і                       ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДї        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і         СТАРОЕ EBP         і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ГЛАВНОЙ программы  і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ГЛАВНОЙ программы  і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ГЛАВНОЙ программы  і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ПРОЦЕДУРЫ А        і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ПРОЦЕДУРЫ А        і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ГЛАВНОЙ программы  і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ПРОЦЕДУРЫ А        і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       і  EBP из ПРОЦЕДУРЫ B        і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   ЪДДДі  EBP из ПРОЦЕДУРЫ B        іДДEBP  і
і                   і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   і   і  EBP из ГЛАВНОЙ программы  і        і
і      ОТОБРАЖЕНИЕ  і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   і   і  EBP из ПРОЦЕДУРЫ А        і        і
і                   і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   АДДДі  EBP из ПРОЦЕДУРЫ B        і        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   ЪДДДі                            і        і
і      ДИНАМИЧЕСКАЯ і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і      ПАМЯТЬ       і   ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                   АДДДі                            іДДESP  і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ        і
і                       АДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ        і
і                                                             і
і                                                             і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
      Рисунок 3-20. Стек данных после запуска ПРОЦЕДУРЫ C
Обратите внимание, что ПРОЦЕДУРА B и ПРОЦЕДУРА С находятся на
одном и том же уровне, поэтому для ПРОЦЕДУРЫ С не предполагается
доступ к переменным ПРОЦЕДУРЫ B. Это не означает, что ПРОЦЕДУРА
С полностью изолирована от ПРОЦЕДУРЫ B; ПРОЦЕДУРА С вызывается
ПРОЦЕДУРОЙ B, поэтому указатель на возвращаемый кадр стека
является указателем на кадр стека ПРОЦЕДУРЫ B. В дополнение к
этому ПРОЦЕДУРА B может передавать параметры в ПРОЦЕДУРЫ С как
через стек, так и через переменные, глобальные по отношению к
обоим процедурам (т.е. переменные сферы действия обоих
процедур).
LEAVE (Выйти из процедуры) противоположна по действию описанной
перед ней команде ENTER.
Команда LEAVE не имеет операндов. Команда LEAVE копирует
содержимое регистра EBP в регистр ESP для того, чтобы освободить
все стековое пространство, зарезервированное для процедуры.
Затем команда LEAVE восстанавливает старое значение регистра EBP
из стека. Одновременно восстанавливается исходное значение
регистра ESP. Следующая команда RET затем может удалить любые
аргументы и адреса возврата, сохраненные в стеке вызываемой
программой для использования в процедуре.
3.8 Команды управления флагами.
----------------------------------------------------------------
Команды управления флагами изменяют состояние битов регистра
EFLAGS, как показано в Таблице 3-5.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДї
і             Команда                і      Результат       і
ГДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДґ
і STC (Установить флаг переноса)     і  CF ДД 1            і
і CLC (Очистить флаг переноса)       і  CF ДД 0            і
і CMC (Дополнить флаг переноса)      і  CF ДД - (CF)       і
і CLD (Очистить флаг направления)    і  DF ДД 0            і
і STD (Установить флаг направления)  і  DF ДД 1            і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДЩ
         Tаблица 3-5. Команды управления флагами.
3.8.1 Команды управления флагами переноса и управления.
----------------------------------------------------------------
Команды работы с флагом переноса используются вместе с
командами, аналогичными командам циклического сдвига с переносом
RCL и RCR. Они могут инициировать флаг переноса CF в известное
состояние перед выполнением команды, которая копирует флаг в
операнд.
Команды управления флагом направления устанавливают или очищают
флаг направления DF, который управляет направлением обработки
строки. Если флаг DF очищен, процессор увеличивает регистры
индекса строк, ESI и EDI, после каждой итерации команды
обработки строки. Если флаг DF установлен, процессор уменьшает
эти индексные регистры.
3.8.2 Команды пересылки флага.
----------------------------------------------------------------
Хотя и существуют специальные команды для изменения флагов CF и
DF, нет прямых методов изменения для остальных флагов,
ориентированных на использование в прикладном программировании.
Команды пересылки флага позволяют программе изменять состояние
других флагов с использованием команд манипуляций с битами, если
только эти флаги были перемещены в стек или в регистр AH.
Команды LAHF и SAHF работают с пятью флагами статуса, которые
используются прежде всего арифметическими и логическими
командами.
LAHF (Загрузить регистр AH из флагов) копирует флаги SF, ZF, AF,
PF и CF в регистр AH, биты 7,6,4,2 и 0 соответственно (смотри
Рисунок 3-21). Содержимое оставшихся битов 5,3, и 1 остается
неопределенным. Содержимое регистра EFLAGS остается неизменным.
SAHF (Сохранить значения регистра AH во флагах) копирует биты
7,6,4,2, и 0 во флаги SF, ZF, AF, PF и CF соответственно (смотри
Рисунок 3-21).
Kоманды PUSHF и POPF не только рекомендуется использовать для
запоминания значения флагов в памяти, где они могут быть
проверены и изменены, но также рекомендуется использовать для
сохранения состояния регистра EFLAGS при выполнении подпрограмм.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і                                                              і
і                     7 6 5 4 3 2 1 0                          і
і                    ЪДВДВДВДВДВДВДВДї                         і
і                    іSіZі0іAі0іPі1іCі                         і
і                    іFіFі іFі іFі іFі                         і
і                    АДБДБДБДБДБДБДБДЩ                         і
і                                                              і
і  БИТОВЫЕ ПОЗИЦИИ ФЛАГОВ ТЕ ЖЕ САМЫЕ, ЧТО И ИХ ПОЗИЦИИ В РЕ-  і
і  ГИСТРЕ EFLAGS ИЛИ В РЕГИСТРЕ AH. БИТОВЫЕ ПОЗИЦИИ, ПОКАЗАН-  і
і  НЫЕ КАК 0 ИЛИ 1, ЯВЛЯЮТСЯ ПОЗИЦИЯМИ, ЗАРЕЗЕРВИРОВАННЫМИ     і
і  КОМПАНИЕЙ INTEL (R). ЭТИ ПОЗИЦИИ ИСПОЛЬЗОВАТЬ ЗАПРЕЩЕНО.    і
і                                                              і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
         Рисунок 3-21. Младший байт регистра EFLAGS.
PUSHF (Сохранить флаги) сохраняет младшее слово регистра EFLAGS
в стеке (смотри Рисунок 3-22). Команда PUSHFD сохраняет целиком
регистр EFLAGS в стеке (тем не менее флаг RF читается как
очищенный).
POPF (Восстановить флаги из стека) восстанавливает слово из
стека в регистр EFLAGS. При всех использованиях этой команды
изменяются значения только битов 14,11,10,8,7,6,4,2 и 0. Если
уровень привилегированности данного программного сегмента равен
0 (самый привилегированный), биты IOPL (13 и 12) также
изменяются. Если уровень привилегий Ввода/Вывода (IOPL) равен 0,
то изменяется также флаг IF (бит 9). Команда POPFD
восстанавливает двойное слово из стека в регистр EFLAGS, и она
может изменять состояние флага AС (бит 18) так же, как и всех
битов, изменяемых по команде POPF.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Дї
і                                                                
 і
і                                                  PUSHFD/POPFD  
 і
і і<ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД>і
 і
і                                                                
 і
і                                                    PUSHF/POPF  
 і
і і<ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД>і
 і
і  31                              15                          0 
 і
і ЪДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДВДї
 і
і і і і і і і і і і і і і і і і і і і іIі і і і і і і і і і і і і
 і
і і і і і і і і і і і і і і іAіNіRі іNіOіOіDіIіTіSіZі іAі іPі іCі
 і
і і0і0і0і0і0і0і0і0і0і0і0і0і0іCіMіFі0іTіPіFіFіFіFіFіFі0іFі0іFі1іFі
 і
і і і і і і і і і і і і і і і і і і і іLі і і і і і і і і і і і і
 і
і АДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДБДЩ
 і
і                                                                
 і
і БИТОВЫЕ ПОЗИЦИИ, ПОМЕЧЕННЫЕ 0 ИЛИ 1, ЗАРЕЗЕРВИРОВАНЫ КОМПАНИЕЙ 
 і
і INTEL (R). ИСПОЛЬЗОВАНИЕ ПОЗИЦИЙ ЗАПРЕЩЕНО.                    
 і
і                                                                
 і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
ДЩ
   Рисунок 3-22. Флаги, используемые командами PUSHF и POPF
3.9 Числовые команды
----------------------------------------------------------------
Процессор i486 включает в себя аппаратуру и команды для
выполнения высокоточных числовых операций над множеством
числовых типов данных, включая 80-разрядное расширенное
вещественное и 64-разрядное длинное целое. Возможно выполнение
арифметических команд, трансцендентных команд, команд сравнения
и преобразования типов данных. Также поддерживаются значения
часто используемых в вычислениях констант, чтобы повысить
скорость числовых вычислений.
Числовые команды встроены в поток команд процессора i486,
поэтому они выполняются одним и тем же устройство, имеющим
возможности как целогочисленного процессора, так и возможности
процессора чисел с плавающей запятой. Но в действительности
устройство работы с чиселами с плавающей запятой ЦПУ i486
работает параллельно с целочисленным устройством, достигая при
этом наивысшей производительности.
ЧАСТЬ III, Главы 14-18 данного руководства, более подробно
описывают числовые команды.
3.10 Команды работы с сегментными регистрами
----------------------------------------------------------------
Существует несколько различных типов команд, которые используют
сегментные регистры. Здесь они сгруппированы все вместе, так
как, если разработчики системы выберут несегментированную модель
организации памяти, ни одна из этих команд не будет
использована. Команды, которые имеют дело с сегментными
регистрами, таковы :
1. Команды пересылки сегмент-регистр.
   MOV   SegReg,...
   MOV   ...,SegReg
   PUSH  SegReg
   POP   SegReg
2. Передача управления другому выполнимому сегменту.
   JMP   дальний
   CALL  дальний
   RET   дальний
3. Команды работы с указателями данных.
   LDS   регистр, 48-разрядный операнд в памяти
   LES   регистр, 48-разрядный операнд в памяти
   LFS   регистр, 48-разрядный операнд в памяти
   LGS   регистр, 48-разрядный операнд в памяти
   LSS   регистр, 48-разрядный операнд в памяти
4. Обратите внимание на то, что следующие связанные с
   прерываниями команды также используются в несегментированных
   системах. Хотя они и могут передавать управление между
   сегментами, когда используется сегментация, они понятны
   прикладному программисту.
   INT   n
   INTO
   BOUND
   IRET
3.10.1 Команды пересылки сегмент-регистр.
----------------------------------------------------------------
Формы команд MOV, POP и PUSH также используются для загрузки и
сохранения сегментных регистров. Эти формы работают как формы с
регистрами общего назначения, за исключением того, что один из
операндов является сегментным регистром. Команда MOV не может
копировать содержимое сегментного регистра в другой сегментный
регистр.
Команды POP и MOV не могут поместить значение в регистр CS
(сегмент кода); только команды дальней передачи управления
оказывают воздействие на регистр CS. Когда преемником является
регистр SS (сегмент стека), запрещаются все прерывания до
момента выполнения следующей команды.
В процессоре 386(R) DX загрузка сегментного регистра всегда
приводит к блокировке циклов чтения и записи путем установки
бита доступа. В процессоре i486 блокировка циклов возникает
только в том случае, если бит доступа не был установлен ранее.
Не требуется никакого 16-разрядного префикса размерности
операнда при передаче данных между сегментным регистром и
32-разрядным регистром общего назначения.
3.10.2 Команды дальней передачи управления.
----------------------------------------------------------------
Команды дальней передачи управления передают управление
преемнику в другом сегменте путем замены содержимого регистра
CS. Преемник задается при помощи дальнего указателя, который
является 16-разрядным селектором сегмента и 32-разрядным
смещением внутри сегмента. Дальний указатель может быть
непосредственным значением или операндом в памяти.
Дальний CALL. Внутрисегментная команда CALL помещает значения,
содержащиеся в регистрах EIP и CS, в стек.
Дальний RET. Внутрисегментная команда RET восстанавливает
значения регистров CS и EIP из стека.
3.10.3 Команды работы указатель на данные
----------------------------------------------------------------
Команды работы с указателями загружают дальний указатель в
регистры процессора. Дальний указатель состоит из 16-разрядного
селектора сегмента, который загружается в сегментный регистр, и
32-разрядного смещения внутри сегмента, которое загружается в
регистр общего назначения.
LDS (Загрузить указатель, используя DS) копирует дальний
указатель из операнда-источника в регистр DS и в регистр общего
назначения. Операнд-источник обязан быть операндом,
расположенным в ячейке памяти, и операнд-преемник должен быть
регистром общего назначения.
    Пример : LDS   ESI, STRING_X
Загружает в регистр DS селектор сегмента для сегмента, адрес
которого задан в STRING_X, и загружает сдвиг внутри сегмента,
адресуемого STRING_X, в регистр ESI. Задание регистра ESI в
качестве операнда-преемника удобно при подготовке к выполнению
операций со строками, когда строка-источник находится не в
текущем сегменте.
LES (Загрузить указатель, используя ES) имеет тот же результат,
что и команда LDS, за исключением того, что селектор сегмента
загружается в регистр ES, а не в регистр DS.
     Пример : LES   EDI, DESTINATION_X
Загружает в регистр ES селектор сегмента для сегмента, адрес
которого задан в DESTINATION_X, и загружает сдвиг внутри
сегмента, адресуемого DESTINATION_X, в регистр EDI. Эта команда
является удобным способом выбора преемника для выполнения команд
работы со строками, если нужное местоположение находится вне
текущего сегмента Е-данных.
LFS  (Загрузить указатель, используя FS) имеет тот же результат,
что и команда LDS, за исключением того, что  значение  селектора
сегмента получает регистр FS, а не регистр DS.
LGS (Загрузить указатель, используя GS) имеет тот же  результат,
что и команда LDS, за исключением того, что  значение  селектора
сегмента получает регистр GS, а не регистр DS.
LSS  (Загрузить указатель, используя SS) имеет тот же результат,
что и команда LDS, за исключением того, что  регистр  SS,  а  не
регистр  DS,  получает значение селектора сегмента.  Эта команда
особенно  важна,  так  как   она   позволяет   двум   регистрам,
идентифицирующим   стек  (регистры  SS  и  ESP),  изменять  свои
значения за одну непрерываемую операцию.  В  отличие  от  другух
команд,  которые  могут  загружать  значения  в  регистр  SS, до
окончания выполнения  команды  LSS  прерывания  не  подавляются.
Другие  команды,  такие,  как  POP  SS, подавляют прерывания для
того, чтобы позволить следующей  команде  загрузить  значение  в
регистр   ESP  без  возникновения  прерывания.   Так  как  обоим
регистрам, и SS, и ESP,  могут  быть  присвоены  значения  одной
командой   LSS,   нет  необходимости  запрещать  и  затем  вновь
разрешать появление прерываний.
3.11 Остальные команды
----------------------------------------------------------------
Следующие команды не попадают ни в одну из вышеприведенных
категорий, но тем не менее не теряют своей значимости.
Команды BSWAP, XADD и CMPXCHG отсутствуют на микропроцессорах
386 DX или 386 SX. ЦПУ 386 может выполнять аналогичные операции
в командах умножения. Для того, чтобы использовать эти команды,
всегда включайте функционально эквивалентный код для ЦПУ 386.
Используйте код, приведенный на Рисунок 3-23 для определения, мог
ут
ли данные команды быть использованы.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
і $title ("Определяет идентификатор ЦПУ для ЦПУ 386 или i486")   
і                                                                
і     name   CPU_ID                                              
і     public   is386                                             
і                                                                
і code     segment       er public use32                         
і ;                                                              
і ; Идентифицирует текущий тип ЦПУ, на котором выполняется работа
і ; Возвращает значения EAX=0 для ЦПУ i486, или EAX=1 для ЦПУ 386
і ; Оставляет неизмененными ESP, EBP, EBH, ESI и EDI             
і is386     proc      near                                       
і     mov    edx,esp           ; сохраняет значение текущего     
і                              ; указателя стека для             
і                              ; выравнивания его                
і     and    esp,not 3         ; выравнивает стек для            
і                              ; избежания ошибки AC             
і     pushfd                   ; сохраняет   EFLAGS              
і     pop    eax               ; получает из стека значение EAX  
і     mov    ecx, eax          ; сохраняет исходное значение     
і                              ; EFLAGS                          
і     xor    eax, 40000H       ; перебрасывает на противоположное
і                              ; значение бита АС                
і     push   eax               ; копирует в EFLAGS               
і     popfd                                                      
і     pushfd                   ; получает новое значение EFLAGS  
і     pop    eax               ; помещает в EAX                  
і     xor    eax, ecx          ; проверяет, если бит АС изменен, 
і                              ; ЕАХ=4000Н, если процессор 386,  
і                              ; 0, если процессор i486          
і     shr    eax, 18           ; устанавливает ЕАХ=1, если ЦПУ   
і                              ; 386, 0, если ЦПУ i486           
і     and    eax, 1            ; игнорирует все остальные биты   
і     push   ecx                                                 
і     popfd                    ; восстанавливает исходное        
і                              ; значение регистра EFLAGS        
і     mov    esp, edx          ; восстанавливает исходное        
і                              ; значение указателя стека        
і     ret                                                        
і is386      endp                                                
і                                                                
і code       ends                                                
і     end                                                        
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
         Рисунок 3-23 Код для определения CPU_ID
3.11.1 Команда вычисления адреса
----------------------------------------------------------------
LEA (Загрузить эффективный адрес) помещает 32-разрядный сдвиг
операнда-источника в памяти (а не его содержимое) в операнд
назначения. Операнд-источник должен находиться в памяти, и
операнд назначения должен быть регистром общего назначения. Эта
команда особенно полезна для инициализации регистров ESI и EDI
перед выполнением команд работы со строками или инициализации
регистра EBX перед командой XLAT. Команда LEA может выполнять
любое необходимое индексирование или масштабирование.
     Пример : LEA   EBX, EBCDIC_TABLE
Заставляет процессор поместить адрес начальной позиции таблицы,
помеченной как EBCDIC_TABLE, в EBX.
3.11.2 Команда нет-операции
----------------------------------------------------------------
NOP (Нет-операции) занимает байт пространства кода. Когда
команда выполняется, она увеличивает регистр EIP так, чтобы он
указывал на следующую команду, но не имеет более никакого
действия.
3.11.3 Команда трансляции.
----------------------------------------------------------------
XLATB (Транслировать) заменяет содержимое регистра AL на байт,
считанный из таблицы трансляции в памяти. Содержимое регистра AL
интерпретируется как целый без знака индекс в этой таблице, с
использованием содержимого регистра EBX в качестве базового
адреса. Команда XLAT делает то же самое и загружает результат в
тот же регистр, но она получает байт-операнд из памяти. Эта
функция используется для преобразования кодов символов из одного
алфавита в другой. Например, код ASCII мовет быть использован
для получения своего эквивалента в кодах EBCDIC.
3.11.4 Команда перестановки байтов.
----------------------------------------------------------------
BSWAP (Переставить байты) меняет порядок байтов в 32-разрядном
регистровом операнде. Битовые позиции 7..0 меняются местами с
позициями 31..24, и позиции 15..8 меняются местами с позициями
23..16. Эта команда полезна при преобразованиях форматов данных
"big-endian" и "little-endian". Выполнение команды BSWAP два
раза подряд оставляет значение регистра без изменений. Эта
команда также ускоряет выполнение команд десятичной арифметики
посредством работы с четырьмя разрядами за один раз, как
показано на Рисунок 3-24. Смотри введение в раздел 3.11
относительно использования команды BSWAP на процессоре 386.
3.11.5 Команда заменить-и-сложить
----------------------------------------------------------------
XADD (Заменить и сложить) использует два операнда:
операнд-источник в регистре и операнд назначения в регистре или
в памяти. Операнд-источник заменяется на операнд назначения, и
преемник заменяется на сумму источника и преемника. Флаги
отражают результат сложения. Эта команда может быть объединена с
командой LOCK в многопроцессорной системе, чтобы позволить
множеству процессоров выполнять один цикл действий. Смотри
введение в раздел 3.11 относительно использования команды XADD
на процессоре 386.
3.11.6 Команда сравнить-и-заменить
----------------------------------------------------------------
CMPXCHG (Сравнить и заменить) использует три операнда :
операнд-источник в регистре, операнд назначения в регистре или в
памяти и аккумулятор (т.е. регистр AL, AX или EAX в зависимости
от размерности операндов). Если значения в преемнике и в
накопителе равны, операнд назначения заменяется на источник. В
противном случае исходное значение операнда назначения
загружается в накопитель. Флаги отражают результат, который
получается при вычитании операнда назначения из аккумулятора.
Флаг ZF устанавливается, если значения операнда назначения и
накопителя равны, в противном случае флаг очищается.
Команда CMPXCHG полезна при тестировании и модификации
семафоров. Она выполняет проверку, чтобы посмотреть, свободен ли
семафор и есть ли такая отметка, в противном случае команда
получает идентификатор текущего владельца в одной непрерываемой
операции. В системах с одним процессором она исключает
необходимость переключения на уровень 0 для блокировки
прерываний для выполнения многократных команд. Для
многопроцессорных систем команда CMPXVHG может быть объединена с
командой LOCK для выполнения всех циклов шины автоматически.
Смотри введение в раздел 3.11 относительно использования команды
CMPXCHG на процессоре 386.
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і                                                              і
і $title   ('ASCII сложение/вычитание с использованием BSWAP') і
і                                                              і
і    name        ASCII_arith                                   і
і                                                              і
і code    segment      er public use32                         і
і ;                                                            і
і ; Сложить 4 десятичных цифры в ASCII-строке все вместе       і
і ; Старшим полубайтом ДОЛЖЕН быть 3                           і
і ; DS:[ESI] указывает на операнд 1                            і
і ; DS:[EBX] указывает на операнд 2                            і
і ; DS:[EDI] указывает на операнд-преемник                     і
і ;                                                            і
і                                                              і
і add10    proc       near                                     і
і                                                              і
і ;                                                            і
і ; Выполняет ASCII сложение с использованием команды BSWAP на і
і ; процессоре i486                                            і
і ;                                                            і
і                                                              і
і   mov     eax,[esi]        ; получает младшие четыре цифры   і
і                            ; первого операнда                і
і   bswap   eax              ; преобразует в форму big-endian  і
і   add     eax,96969696H    ; выравнивает для сложения        і
і   mov     ecx,[ebx]        ; получает четыре младшие цифры   і
і                            ; второго операнда                і
і   bswap   ecx              ; преобразует в форму big-endian  і
і   add     eax,ecx          ; выполняет сложение с внутрираз- і
і                            ; рядным переносом                і
і   rcr     ch,1             ; сохраняет флаг переноса         і
і   mov     edx,eax          ; сохраняет значение              і
і   and     eax,0F0F0F0F0H   ; извлекает старший полубайт      і
і   sub     edx,eax          ; заполняет нулями старший        і
і                            ; полубайт каждого байта          і
і   shr     eax,4            ; подготавливает для фиксации     і
і   and     eax,0A0A0A0AH    ; если ненулевой старший полу-    і
і                            ; байт, то сформоровать 10 как    і
і                            ; выравнивающее значение для      і
і                            ; младшего полубайта              і
і   add     eax,edx          ; формируется выровненное значе-  і
і                            ; ние младшего полубайта, старшие і
і                            ; полубайты могут быть 1 из       і
і                            ; выравнивания                    і
і   or      eax,30303030H    ; преобразовать обратно в ASCII   і
і   bswap   eax              ; обратно в форму little-endian   і
і   mov     [edi],eax        ; установить значение преемника   і
і   rcl     ch,1             ; восстановить флаг перенос       і
і   ret                                                        і
і                                                              і
і add10     endp                                               і
і                                                              і
і ;                                                            і
і ; Вычесть 4 десятичных цифры в ASCII-строке все вместе       і
і ; Старшим полубайтом ДОЛЖЕН быть 3                           і
і ; DS:[ESI] указывает на операнд 1                            і
і ; DS:[EBX] указывает на операнд 2   [ESI]-[EBX]              і
і ; DS:[EDI] указывает на операнд-преемник                     і
і ;                                                            і
і                                                              і
і sub10    proc     near                                       і
і                                                              і
і ;                                                            і
і ; Выполняет ASCII вычитание с использованием команды BSWAP наі
і ; процессоре i486                                            і
і ;                                                            і
і                                                              і
і   mov     eax,[esi]        ; получает младшие четыре цифры   і
і                            ; первого операнда                і
і   bswap   eax              ; преобразует в форму big-endian  і
і   mov     ecx,[ebx]        ; получает четыре младшие цифры   і
і                            ; второго операнда                і
і   bswap   ecx              ; преобразует в форму big-endian  і
і   sub     eax,ecx          ; выполняет вычитание с исполь-   і
і                            ; зованием внутриразрядного заема і
і                            ; единицы                         і
і   rcr     ch,1             ; сохраняет флаг переноса         і
і   mov     edx,eax          ; сохраняет значение              і
і   and     eax,0F0F0F0F0H   ; извлекает старший полубайт, F,  і
і                            ; если возникает заем единицы     і
і   sub     edx,eax          ; заполняет нулями старший        і
і                            ; полубайт каждого байта          і
і   shr     eax,4            ; подготавливает для фиксации     і
і   and     eax,0A0A0A0AH    ; если ненулевой старший полу-    і
і                            ; байт, то сформоровать 10 как    і
і                            ; выравнивающее значение для      і
і                            ; младшего полубайта              і
і   add     eax,edx          ; формируется выровненное значе-  і
і                            ; ние младшего полубайта, старшие і
і                            ; полубайты могут быть 1 из       і
і                            ; выравнивания                    і
і   or      eax,30303030H    ; преобразовать обратно в ASCII   і
і   bswap   eax              ; обратно в форму little-endian   і
і   mov     [edi],eax        ; установить значение преемника   і
і   rcl     ch,1             ; восстановить флаг заема единицы і
і   ret                                                        і
і                                                              і
і sub10     endp                                               і
і                                                              і
і code      ends                                               і
і   end                                                        і
і                                                              і
АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
 Рисунок 3-24. ASCII арифметика с использованием команды BSWAP


Яндекс цитирования