Цепочечные команды
Эти команды также называют командами обработки строк символов. Названия почти синонимичны.
Отличие в том, что под строкой символов здесь понимается последовательность байт, а цепочка — это более общее название для случаев, когда элементы последовательности имеют размер больше байта — слово или двойное слово.
Таким образом, цепочечные команды позволяют проводить действия над блоками памяти, представляющими собой последовательности элементов следующего размера:
8 бит — байт;
16 бит — слово;
32 бита — двойное слово.
Содержимое этих блоков для микропроцессора не имеет никакого значения. Это могут быть символы, числа и все что угодно. Главное, чтобы размерность элементов совпадала с одной из перечисленных и эти элементы находились в соседних ячейках памяти.
Всего в системе команд микропроцессора имеется семь операций-примитивов
обработки цепочек.
Каждая из них реализуется в микропроцессоре тремя командами, в свою очередь, каждая из этих команд работает с соответствующим размером элемента — байтом, словом или двойным словом.
Особенность всех цепочечных команд в том, что они, кроме обработки текущего элемента цепочки, осуществляют еще и автоматическое продвижение к следующему элементу данной цепочки.
Перечислим операции-примитивы и команды, с помощью которых они реализуются, а затем подробно их рассмотрим:
пересылка цепочки:
- адрес_приемника,адрес_источника
сравнение цепочек:
- адрес_приемника,адрес_источника
сканирование цепочки:
- адрес_приемника
загрузка элемента из цепочки:
- адрес_источника
сохранение элемента в цепочке:
- адрес_приемника
получение элементов цепочки из порта ввода-вывода:
- адрес_приемника,номер_порта
вывод элементов цепочки в порт ввода-вывода:
- номер_порта,адрес_источника
Логически к этим командам нужно отнести и так называемые префиксы повторения. Вспомните и его первые необязательные байты префиксов. Один из возможных типов префиксов — это префиксы повторения. Они предназначены для использования цепочечными командами.
Префиксы повторения имеют свои мнемонические обозначения:
rep
repe или repz
repne или repnz
Эти префиксы повторения указываются перед нужной цепочечной командой в поле метки.
Цепочечная команда без префикса выполняется один раз. Размещение префикса перед цепочечной командой заставляет ее выполняться в цикле.
Отличия приведенных префиксов в том, на каком основании принимается решение о циклическом выполнении цепочечной команды: по состоянию регистра ecx/cx или по флагу нуля zf:
префикс повторения rep (REPeat). Этот префикс используется с командами, реализующими операции-примитивы пересылки и сохранения элементов цепочек — соответственно, movs и stos.
Префикс rep заставляет данные команды выполняться, пока содержимое в ecx/cx не станет равным 0.
При этом цепочечная команда, перед которой стоит префикс, автоматически уменьшает содержимое ecx/cx на единицу. Та же команда, но без префикса, этого не делает;
префиксы повторения repe или repz (REPeat while Equal or Zero). Эти префиксы являются абсолютными синонимами.
Они заставляют цепочечную команду выполняться до тех пор, пока содержимое ecx/cx не равно нулю или флаг zf равен 1.
Как только одно из этих условий нарушается, управление передается следующей команде программы. Благодаря возможности анализа флага zf, наиболее эффективно эти префиксы можно использовать с командами cmps и scas для поиска отличающихся элементов цепочек.
префиксы повторения repne или repnz (REPeat while Not Equal or Zero). Эти префиксы также являются абсолютными синонимами. Их действие на цепочечную команду несколько отличается от действий префиксов repe/repz. Префиксы repne/repnz заставляют цепочечную команду циклически выполняться до тех пор, пока содержимое ecx/cx не равно нулю или флаг zf равен нулю.
При невыполнении одного из этих условий работа команды прекращается.
Данные префиксы также можно использовать с командами cmps и scas, но для поиска совпадающих элементов цепочек.
Следующий важный момент, связанный с цепочечными командами, заключается в особенностях формирования физического адреса операндов адрес_источника и адрес_приемника.
Цепочка-источник, адресуемая операндом адрес_источника, может находиться в текущем сегменте данных, определяемом регистром ds.
Цепочка-приемник, адресуемая операндом адрес_приемника, должна быть в дополнительном сегменте данных, адресуемом сегментным регистром es.
Важно отметить, что допускается замена (с помощью префикса замены сегмента) только регистра ds, регистр es подменять нельзя.
Вторые части адресов - смещения цепочек — также находятся в строго определенных местах.
Для цепочки-источника это регистр esi/si
(Source Index register — индексный регистр источника).
Для цепочки-получателя это регистр edi/di
(Destination Index register - индексный регистр приемника).
Таким образом, полные физические адреса для операндов цепочечных команд следующие:
адрес_источника — пара ds:esi/si;
адрес_приемника — пара es:edi/di.
Вы, наверное обратили внимание на то, что все семь групп команд, реализующих цепочечные операции-примитивы, имеют похожий по структуре набор команд.
В каждом из этих наборов присутствует одна команда с явным указанием операндов и три команды, не имеющие операндов.
На самом деле, набор команд микропроцессора имеет соответствующие машинные команды только для цепочечных команд ассемблера без операндов. Команды с операндами транслятор ассемблера использует только для определения типов операндов.
После того как выяснен тип элементов цепочек по их описанию в памяти, генерируется одна из трех машинных команд для каждой из цепочечных операций. По этой причине все регистры, содержащие адреса цепочек, должны быть инициализированы заранее, в том числе и для команд, допускающих явное указание операндов.
В силу того, что цепочки адресуются однозначно, нет особого смысла применять команды с операндами. Главное, что вы должны запомнить, — правильная загрузка регистров указателями обязательно требуется до выдачи любой цепочечной команды.
Последний важный момент, касающийся всех цепочечных команд, — это направление обработки цепочки. Есть две возможности:
от начала цепочки к ее концу, то есть в направлении возрастания адресов;
от конца цепочки к началу, то есть в направлении убывания адресов.
Как мы увидим ниже, цепочечные команды сами выполняют модификацию регистров, адресующих операнды, обеспечивая тем самым автоматическое продвижение по цепочке. Количество байт, на которые эта модификация осуществляется, определяется кодом команды. А вот знак этой модификации определяется значением флага направления df (Direction Flag) в регистре eflags/flags:
если df = 0, то значение индексных регистров esi/si и edi/di будет автоматически увеличиваться (операция инкремента) цепочечными командами, то есть обработка будет осуществляться в направлении возрастания адресов;
если df = 1, то значение индексных регистров esi/si и edi/di будет автоматически уменьшаться (операция декремента) цепочечными командами, то есть обработка будет идти в направлении убывания адресов.
Состоянием флага df можно управлять с помощью двух команд, не имеющих операндов:
(Clear Direction Flag) — очистить флаг направления. Команда сбрасывает флаг направления df в 0.
(Set Direction Flag) — установить флаг направления. Команда устанавливает флаг направления df в 1.
Это вся информация, касающаяся общих свойств цепочечных команд. Далее мы более подробно рассмотрим каждую операцию-примитив и команды, которые ее реализуют. При этом более подробно мы будем рассматривать одну команду в каждой группе цепочечных команд — команду с операндами. Это будет делаться из тех соображений, что это более общая команда в смысле ограничений, накладываемых на типы операндов.