Содержимое операнда сдвигается влево на количество бит, определяемое операндом счетчик_сдвигов. Сдвигаемые биты поочередно становятся значением флага переноса cf.
2) гсг операнд, счетчик_сдвигов (Rotate through Carry Right) – циклический сдвиг вправо через перенос.
Содержимое операнда сдвигается вправо на количество бит, определяемое операндом счетчик_сдвигов. Сдвигаемые биты поочередно становятся значением флага переноса СF.
Рис. 33. Команды циклического сдвига через флаг переноса CF
Из рисунка 33 видно, что при сдвиге через флаг переноса появляется промежуточный элемент, с помощью которого, в частности, можно производить подмену циклически сдвигаемых битов, в частности, рассогласование битовых последовательностей.
Под рассогласованием битовой последовательности здесь и далее подразумевается действие, которое позволяет некоторым образом локализовать и извлечь нужные участки этой последовательности и записать их в другое место.
Система команд последних моделей микропроцессоров Intel, начиная с i80386, содержит дополнительные команды сдвига, расширяющие возможности, рассмотренные нами ранее. Это – команды сдвигов двойной точности: 1) shld операнд_1, операнд_2, счетчик_сдвигов – сдвиг влево двойной точности. Команда shld производит замену путем сдвига битов операнда операнд_1 влево, заполняя его биты справа значениями битов, вытесняемых из операнд_2 согласно схеме на рис. 34. Количество сдвигаемых бит определяется значением счетчик_сдвигов, которое может лежать в диапазоне 0… 31. Это значение может задаваться непосредственным операндом или содержаться в регистре cl. Значение операнд_2 не изменяется.
Рис. 34. Схема работы команды shld
2) shrd операнд_1, операнд_2, счетчик_сдвигов – сдвиг вправо двойной точности. Команда производит замену путем сдвига битов операнда операнд_1 вправо, заполняя его биты слева значениями битов, вытесняемых из операнд_2 согласно схеме на рисунке 35. Количество сдвигаемых бит определяется значением счетчик_сдвигов, которое может лежать в диапазоне 0… 31. Это значение может задаваться непосредственным операндом или содержаться в регистре cl. Значение операнд_2 не изменяется.
Рис. 35. Схема работы команды shrd
Как мы отметили, команды shld и shrd осуществляют сдвиги до 32 разрядов, но за счет особенностей задания операндов и алгоритма работы эти команды можно использовать для работы с полями длиной до 64 бит.
2. Команды передачи управления
Мы познакомились с некоторыми командами, из которых формируются линейные участки программы. Каждая из них в общем случае выполняет некоторые действия по преобразованию или пересылке данных, после чего микропроцессор передает управление следующей команде. Но очень мало программ работает таким последовательным образом. Обычно в программе есть точки, в которых нужно принять решение о том, какая команда будет выполняться следующей. Это решение может быть:
1) безусловным – в данной точке необходимо передать управление не той команде, которая идет следующей, а другой, которая находится на некотором удалении от текущей команды;
2) условным – решение о том, какая команда будет выполняться следующей, принимается на основе анализа некоторых условий или данных.
Программа представляет собой последовательность команд и данных, занимающих определенное пространство оперативной памяти. Это пространство памяти может быть либо непрерывным, либо состоять из нескольких фрагментов.
То, какая команда программы должна выполняться следующей, микропроцессор узнает по содержимому пары регистров cs:(e)ip:
1) cs – сегментный регистр кода, в котором находится физический (базовый) адрес текущего сегмента кода;
2) eip/ip – регистр указателя команды, в котором находится значение, представляющее собой смещение в памяти следующей команды, подлежащей выполнению, относительно начала текущего сегмента кода.
Какой конкретно регистр будет использоваться, зависит от установленного режима адресации use16 или use32. Если указано use 16, то используется ip, если use32, то используется eip.
Таким образом, команды передачи управления изменяют содержимое регистров cs и eip/ip, в результате чего микропроцессор выбирает для выполнения не следующую по порядку команду программы, а команду в некотором другом участке программы. Конвейер внутри микропроцессора при этом сбрасывается.
По принципу действия команды микропроцессора, обеспечивающие организацию переходов в программе, можно разделить на 3 группы:
1. Команды безусловной передачи управления:
1) команда безусловного перехода;
2) команда вызова процедуры и возврата из процедуры;
3) команда вызова программных прерываний и возврата из программных прерываний.
2. Команды условной передачи управления:
1) команды перехода по результату команды сравнения стр;
2) команды перехода по состоянию определенного флага;
3) команды перехода по содержимому регистра есх/сх.
3. Команды управления циклом:
1) команда организации цикла со счетчиком есх/сх;
2) команда организации цикла со счетчиком есх/сх с возможностью досрочного выхода из цикла по дополнительному условию.
Предыдущее обсуждение выявило некоторые детали механизма перехода. Команды перехода модифицируют регистр указателя команды eip/ip и, возможно, сегментный регистр кода cs. Что именно должно подвергнуться модификации, зависит:
1) от типа операнда в команде безусловного перехода (ближний или дальний);
2) от указания перед адресом перехода (в команде перехода) модификатора; при этом сам адрес перехода может находиться либо непосредственно в команде (прямой переход), либо в регистре или ячейке памяти (косвенный переход).
Модификатор может принимать следующие значения:
1) near ptr – прямой переход на метку внутри текущего сегмента кода. Модифицируется только регистр eip/ip (в зависимости от заданного типа сегмента кода use16 или use32) на основе указанного в команде адреса (метки) или выражения, использующего символ извлечения значения – $;
2) far ptr – прямой переход на метку в другом сегменте кода. Адрес перехода задается в виде непосредственного операнда или адреса (метки) и состоит из 16-битного селектора и 16/32-битного смещения, которые загружаются, соответственно, в регистры cs и ip/eip;
3) word ptr – косвенный переход на метку внутри текущего сегмента кода. Модифицируется (значением смещения из памяти по указанному в команде адресу, или из регистра) только eip/ip. Размер смещения 16 или 32 бит;
4) dword ptr – косвенный переход на метку в другом сегменте кода. Модифицируются (значением из памяти – и только из памяти, из регистра нельзя) оба регистра – cs и eip/ip. Первое слово/двойное слово этого адреса представляет смещение и загружается в ip/eip; второе/третье слово загружается в cs. Команда безусловного перехода jmp
Синтаксис команды безусловного перехода – jmp [модификатор] адрес_перехода – безусловный переход без сохранения информации о точке возврата.
Адрес_перехода представляет собой адрес в виде метки либо адрес области памяти, в которой находится указатель перехода.
Всего в системе команд микропроцессора есть несколько кодов машинных команд безусловного перехода jmp.
Их различия определяются дальностью перехода и способом задания целевого адреса. Дальность перехода определяется местоположением операнда адрес_перехода. Этот адрес может находиться в текущем сегменте кода или в некотором другом сегменте. В первом случае переход называется внутрисегментным, или близким, во втором – межсегментным, или дальним. Внутрисегментный переход предполагает, что изменяется только содержимое регистра eip/ip.
Можно выделить три варианта внутрисегментного использования команды jmp:
1) прямой короткий;
2) прямой;
3) косвенный.
Процедуры
В языке ассемблера есть несколько средств, решающих проблему дублирования участков программного кода. К ним относятся:
1) механизм процедур;
2) макроассемблер;
3) механизм прерываний.
Процедура, часто называемая также подпрограммой, – это основная функциональная единица декомпозиции (разделения на несколько частей) некоторой задачи. Процедура представляет собой группу команд для решения конкретной подзадачи и обладает средствами получения управления из точки вызова задачи более высокого уровня и возврата управления в эту точку.
В простейшем случае программа может состоять из одной процедуры. Другими словами, процедуру можно определить как правильным образом оформленную совокупность команд, которая, будучи однократно описана, при необходимости может быть вызвана в любом месте программы.
Для описания последовательности команд в виде процедуры в языке ассемблера используются две директивы: PROC и ENDP.
Синтаксис описания процедуры таков (рис. 36).
Рис. 36. Синтаксис описания процедуры в программе
Из рисунка 36 видно, что в заголовке процедуры (директиве PROC) обязательным является только задание имени процедуры. Среди большого количества операндов директивы PROC следует особо выделить [расстояние]. Этот атрибут может принимать значения near или far и характеризует возможность обращения к процедуре из другого сегмента кода. По умолчанию атрибут [расстояние] принимает значение near.
Процедура может размещаться в любом месте программы, но так, чтобы на нее случайным образом не попало управление. Если процедуру просто вставить в общий поток команд, то микропроцессор будет воспринимать команды процедуры как часть этого потока и, соответственно, будет осуществлять выполнение команд процедуры.