Команды процессора сдвиги без переноса
Вы здесь: Главная Процессор Система команд процессора Команды обработки
Архитектура ЭВМ
Сдвиги
Операция сдвига состоит в одновременном перемещении содержимого операнда в разрядной сетке. Существует 3 разновидности операции сдвигов, которые различаются тем, что происходит с битами, выходящими за пределы разрядной сетки с одного "конца" операнда, и с освобождающимися позициями на другом его "конце".
Продолжаем наше краткое, обзорное, знакомство с системой команд процессоров микроконтроллеров. В предыдущей статье "Микроконтроллеры для начинающих. Часть 20. Команды логических операций" я рассказал о командах логических операций. В общем и целом, логических операций достаточно для работы с отдельными битами ячеек памяти.
Однако, это не очень удобно, так как приходится работать с битовыми масками. Кроме того, теоретически (именно теоретически!), битовые операции позволяют избежать последовательности чтение-модификация-запись для ячейки памяти в целом. А это может быть важно, если учесть, что ячейка памяти может быть аппаратным регистром управляющим каким-либо устройством. Этого вопроса мы будем еще не раз касаться при знакомстве с различными узлами и модулями микроконтроллеров. К сожалению, во многих (в большинстве) микроконтроллеров битовые команды все таки неявно воздействуют на ячейку памяти целиком.
Еще одним примером необходимости использования именно битовых команд может являться регистр состояния процессора. Дело в том, что этот регистр может и не иметь адреса, а вот устанавливать/сбрасывать флаги состояний все таки нужно.
Поскольку манипуляции с битами в меньшей степени знакомы новичкам и вызывают больше сложностей в понимании, да и ошибок бывает больше, я рассмотрю их подробнее, чем команды, которые мы рассматривали раньше.
Самое читаемое
- Арифметико логическое устройство (АЛУ)
- Страничный механизм в процессорах 386+. Механизм трансляции страниц
- Организация разделов на диске
- Диск Picture CD
- White Book/Super Video CD
- Прямой доступ к памяти, эмуляция ISA DMA (PC/PCI, DDMA)
- Карты PCMCIA: интерфейсы PC Card, CardBus
- Таблица дескрипторов прерываний
- Разъемы процессоров
- Интерфейс Slot A
Упражнение
Логический сдвиг вправо
Логический сдвиг всегда выполняется без учёта знакового бита. Для логического сдвига вправо предназначена команда SHR . У этой команды два операнда. Первый операнд представляет собой сдвигаемое значение и на его место записывается результат операции. Второй операнд указывает, на сколько бит нужно осуществить сдвиг. Этим операндом может быть либо непосредственное значение, либо регистр CL . Схема выполнения операции показана на рисунке:
Все биты операнда сдвигаются вправо (от старших битов к младшим). Выдвинутый бит становится значением флага CF . Старший бит получает нулевое значение. Эта операция повторяется несколько раз, если второй операнд больше единицы. Логический сдвиг вправо можно использовать для деления целых чисел без знака на степень 2, причём сдвиг работает быстрее, чем команда деления DIV . Примеры:
Пример программы
Программа печатает переменную размером 16-бит в двоичном виде. Используется команда сдвига влево на 1 бит, после чего анализируется значение флага CF . Если CF=0 , выводим символ ‘0’, если СF=1 выводим символ ‘1’. Проверка битов осуществляется в цикле.
Результат работы программы:
Команды обработки
Неявная адресация бита
Команды установки/сброса флагов состояния процессора подразумевают, что выполняется модификация регистра состояния процессора, и никакого иного. А значит, указывать адрес ячейки памяти нет необходимости. А номер бита в таких командах, точнее, его мнемоническое обозначение, задается собственно мнемоникой команды.
Например, команда CLC в микроконтроллерах AVR сбрасывает флаг переноса (бит 0) регистра SREG.
Упражнение
Объявите массив из 8 слов без знака. Сдвиньте первый элемент на 1 бит влево, второй элемент — на 2 бита вправо (логическим сдвигом), третий элемент — на 3 бита влево и т.д. до конца массива. Используйте циклы. Проверьте работу программы в отладчике. Результаты можете выкладывать в комментариях.
Базовую систему команд микропроцессора можно условно разделить на несколько групп по функциональному назначению:
Кроме базовой системы команд микропроцессора существуют также команды расширений:
- X87 – расширение, содержащее команды математического сопроцессора (работа с вещественными числами)
- MMX – расширение, содержащее команды для кодирования/декодирования потоковых аудио/видео данных;
- SSE – расширение включает в себя набор инструкций, который производит операции со скалярными и упакованными типами данных;
- SSE2 – модификация SSE, содержит инструкции для потоковой обработки целочисленных данных, что делает это расширение более предпочтительным для целочисленных вычислений, нежели использование набора инструкций MMX, появившегося гораздо раньше;
- SSE3, SSE4 – содержат дополнительные инструкции расширения SSE.
В таблице команд приняты следующие обозначения:
r – регистр
m – ячейка памяти
c – константа
8, 16, 32 – размер в битах
На все базовые команды процессора накладываются следующие ограничения:
- Нельзя в одной команде оперировать двумя областями памяти одновременно. Если такая необходимость возникает, то нужно использовать в качестве промежуточного буфера любой доступный в данный момент регистр общего назначения.
- Нельзя оперировать сегментным регистром и значением непосредственно из памяти. Поэтому для выполнения такой операции нужно использовать промежуточный объект. Это может быть регистр общего назначения или стек.
- Нельзя оперировать двумя сегментными регистрами. Это объясняется тем, что в системе команд нет соответствующего кода операции. Но необходимость в таком действии часто возникает. Выполнить такую пересылку можно, используя в качестве промежуточных регистры общего назначения. Например,
Команды передачи данных
Основной командой передачи данных является команда MOV , осуществляющая операцию присваивания:
Команда MOV присваивает значению операнда приемника значение операнда источника. В качестве приемника могут выступать регистр общего назначения, сегментный регистр или ячейка памяти, в качестве источника могут выступать константа, регистр общего назначения, сегментный регистр или ячейка памяти. Оба операнда должны быть одного размера.
Команды передачи данных представлены в таблице.
Команды установки единичного бита
Проверяют условие состояния битов регистра EFLAGS и, если условие выполняется, то младший бит операнда устанавливается в 1, в противном случае в 0. Анализ битов производится аналогично условным переходам.
Команды работы со стеком
Команды ввода-вывода
Команды целочисленной арифметики
Особого внимания среди рассмотренных команд целочисленной арифметики заслуживает команда CMP , которая вычитает второй операнд из первого и не сохраняет результат, а устанавливает биты OF, SF, ZF, AF, PF, CF регистра признаков EFLAGS в соответствии с результатом. Команда CMP чаще всего предшествует командам знакового или беззнакового условных переходов.
Логические команды
Выполнение логических операций описано здесь
Сдвиговые команды
Выполнение сдвиговых операций в языке Си рассмотрено здесь .
Команды циклического сдвига выполняются в соответствии со схемой
Команды коррекции двично-десятичных чисел
Команды коррекции двоично-десятичных чисел не имеют операндов и используют операнд по умолчанию, хранящийся в регистре AX (паре регистров AH:AL ).
Команды преобразования типов
Команды преобразования типов предназначены для корректного изменения размера операнда, заданного неявно в регистре-аккумуляторе ( EAX , AX , AL ). Непосредственно после аббревиатуры команды операнд не указывается.
Команды управления флагами
Команды управления флагами предназначены для сброса или установки соответствующего бита регистра признаков EFLAGS . Команды управления флагами не имеют операндов.
Команды прерываний
Команды передачи управления
Команды обращения к процедуре (функции)
Команды поддержки языков высокого уровня
Команды организации циклов — используют регистр ECX по умолчанию в качестве счетчика числа повторений цикла. Каждый раз при выполнении команды LOOPсс значение регистра ECX уменьшается на 1, а затем сравнивается с 0. Если ECX =0 , выполнение цикла заканчивается, и продолжает выполняться код программы, записанный после команды LOOPcc . Если ECX содержит ненулевое значение, то осуществляется переход по адресу операнда команды LOOPcc .
Команды условных переходов — проверяют состояние одного или нескольких битов регистра признаков и при выполнении условия осуществляют передачу программного управления в другую точку кода, задаваемую операндом. Указанный класс команд не запоминает информацию для возврата. Операнд определяет адрес команды, которой должно быть передано управление.
Статья основана на материале xrnd с сайта asmworld (из учебного курса по программированию на ассемблер 16-битного процессора 8086 под DOS).
Циклический сдвиг отличается от линейного тем, что выдвигаемые с одного конца биты вдвигаются с другой стороны, то есть движутся по кольцу. В процессора x86 существует 2 вида циклического сдвига: простой и через флаг переноса ( CF ). У всех команд, рассматриваемых в этой части учебного курса, по 2 операнда, таких же, как у команд линейного сдвига. Первый операнд — сдвигаемое значение и место для записи результата. Второй операнд — счётчик сдвигов, который может находится в регистре CL или указываться непосредственно.
Арифметические команды
Минимальный набор арифметических команд очень мал. Это (например):
- сложение — ADD;
- инвертирование — COM / NOT (такая ЭВМ действительно была: PDP-8 (DEC));
- прибавление "единицы" — INC.
Все остальное можно сделать, комбинируя эти команды.
Однако в современном микропроцессоре арифметических команд обычно больше:
- SUB — вычитание;
- CMP — сравнение операндов. Эта команда выполняет вычитание операндов, по результату изменяет флаги, после чего результат теряется (команда предназначена для проверки условий);
- NEG — смена знака операнда;
- ASR, ASL, SAR, SAL — арифметические сдвиги операнда (Arithmetic Shift to Right/Left);
- INC, DEC — увеличение или уменьшение операнда на 1;
- ADC, SBC/SBB - операции с переносом C (carry-bit) — для выполнения действий с повышенной точностью, когда операнд занимает несколько слов;
- SXT, SEX, CBW, CWD, CDQ — расширение знака (преобразование в формат с повышенной разрядностью);
- MUL, DIV — умножение и деление беззнаковых и знаковых чисел.
- Набор операций с плавающей точкой, включающий обычно значительное количество команд (несколько десятков), в которые часто входят команды вычисления элементарных функций — Sin, Cos, Log, Exp и т.п.
Арифметический сдвиг вправо
Арифметический сдвиг отличается от логического тем, что он не изменяет значение старшего бита, и предназначен для чисел со знаком. Арифметический сдвиг вправо выполняется командой SAR . У этой команды тоже 2 операнда, аналогично команде SHR . Схема выполнения операции показана на рисунке:
Выдвинутый бит становится значением флага CF . Знаковый бит не изменяется. При сдвиге на 1 бит сбрасывается флаг OF . Эту команду можно использовать для деления целых чисел со знаком на степень 2 (обратите внимание, что «округление» всегда в сторону меньшего числа, поэтому для отрицательных чисел результат будет отличаться от результата деления с помощью команды IDIV ). Примеры:
Интерфейсы
Мини блог
Пример программы
В качестве примера напишем программу для подсчёта единичных битов в байте. Для анализа битов используется команда ROL в цикле. Цикл выполняется 8 раз — по числу битов в байте. Если очередной бит равен 1, то выполняем инкремент счётчика единичных битов.
Эту программу можно немного оптимизировать. Во-первых, использовать вместо условного перехода команду ADC со нулевым вторым операндом. Это позволит прибавить 1, если CF=1 и прибавить 0, если CF=0 . Во-вторых, считать единичные биты можно в регистре AH , а обнулить его в начале с помощью команды MOVZX , совместив с загрузкой байта в регистр AL . Ноль для команды ADC можно взять в регистре CH , это делает команду короче и быстрее, чем при использовании непосредственного операнда. CH равен 0 во время выполнения цикла, так как CX изменяется от 8 до 0. Вот что получилось в итоге:
Всего 6 команд для подсчета битов в байте. А попробуйте написать то же самое на языке высокого уровня ?
Архитектура ЭВМ
Адрес бита
Это пример адресации бита в STM8 (команда установки бита), в других микроконтроллерах формат отличается, но принцип такой же. Биты обычно нумеруются начиная с младшего, от 0 до 7. Но бывают и исключения, особенно если говорить о процессорах в целом, включая специализированные.
При этом у нас возникает проблема, для рассматриваемых нами микроконтроллеров. Дело в том, что команды одноадресные. Поэтому номер бита задается в виде непосредственного операнда, в коде команды. Это может оказаться неудобным если номер бита должен изменяться. В таком случае приходится все таки пользоваться командами логических операций.
Простой циклический сдвиг
Значение последнего выдвигаемого бита копируется в флаг CF . Для сдвигов на 1 бит устанавливается флаг OF , если в результате сдвига изменяется знаковый бит операнда. (Честно говоря, не помню, чтобы я этим когда-то пользовался. Но может вам пригодится ? ) Примеры использования команд:
Компоненты ПК
Логический и арифметический сдвиг влево
Логический сдвиг влево выполняется командой SHL , а арифметический — командой SAL . Однако, на самом деле это просто синонимы для одной и той же машинной команды. Сдвиг влево одинаков для чисел со знаком и чисел без знака. У команды 2 операнда, аналогично командам SHR и SAR . Схема этой операции показана на рисунке:
Старший бит становится значением флага CF , а младший получает нулевое значение. С помощью сдвига влево можно быстро умножать числа на степень 2. Но будьте внимательны, чтобы не получить в результате переполнение. Если при сдвиге на 1 бит меняется значение старшего бита, то устанавливается флаг OF. Примеры использования команды:
Циклический сдвиг через флаг переноса
Отличие от простого циклического сдвига в том, что флаг CF участвует в сдвиге наравне с битами операнда. При сдвиге на 1 бит выдвигаемый бит помещается в CF , а значение CF вдвигается в операнд с другой стороны. При сдвиге на несколько бит эта операция повторяется многократно. Циклический сдвиг через флаг переноса выполняется командами RCR (вправо) и RCL (влево).
Опять же для сдвигов на 1 бит устанавливается флаг OF , если в результате сдвига изменяется знаковый бит операнда. Примеры использования команд:
Сдвиги двойной точности
Существуют ещё две команды, осуществляющие более сложные сдвиги. SHRD — сдвиг двойной точности вправо, SHLD — сдвиг двойной точности влево. У этих команд 3 операнда. Первый операнд — сдвигаемое значение и место для записи результата, должен иметь размер 16 бит. Второй операнд — источник вдвигаемых битов, тоже должен иметь размер 16 бит и находится в одном из регистров. Значение второго операнда не меняется. Третий операнд — счётчик сдвигов, может быть непосредственным значением или находиться в регистре CL . Схемы работы этих команд показаны на рисунке:
Небольшой пример использования команды SHLD :
Прямой адрес бита
Я не рассматриваю в данном цикле статей микроконтроллеры архитектуры MCS-51. Однако, интересно продемонстрировать еще один, редко встречающийся, способ адресации бит. Я уже говорил в статьях и комментариях о нем, но немного напомню.
Дело в том, что в MCS-51 есть диапазон адресов байт от 20h до 2Fh, где каждый бит имеет и свой собственный адрес в диапазоне 00h - 7Fh.
Статья основана на материале xrnd с сайта asmworld (из учебного курса по программированию на ассемблер 16-битного процессора 8086 под DOS).
Сдвиги — это особые операции процессора, которые позволяют реализовать различные преобразования данных, работать с отдельными битами, а также быстро выполнять умножение и деление чисел на степень 2. В этой части мы рассмотрим операции линейного сдвига, а в следующей будут циклические.
Логические команды
Логические команды — это команды побитовой обработки.
- OR — поразрядное логическое сложение. Фактически это команда побитовой установки (т.е. записи "единицы" в заданные биты операнда). Пример:
or opr, 0Ch ;Установка в 1 битов в позициях 2 и 3 в операнде al
Если исходно в al содержался, например, операнд 1101 10012, то после выполнения команды в al будет содержаться: 1101 11 01 (отмечены установленные биты). Второй операнд — обычно константа, задавая которую, программист указывает, какие биты следует установить (он на жаргоне программистов носит название "маска").
Можно описать действие команды OR следующим образом: команда безусловно устанавливает в "единицу" биты в тех позициях первого операнда, которые отмечены "единицами" во втором операнде (в маске), оставляя прочие биты первого операнда неизменными.
- AND — поразрядное логическое умножение. Это команда побитового сброса (записи в заданные биты "нулей"). Пример:
and bh, 0Fh ;Сброс старшей тетрады (старшего ниббла) в байтовом операнде.
Если, например, исходно в регистре bh содержался операнд 1101 10012, то после выполнения команды в регистре bh будет содержаться 0000 10012 (отмечены очищенные биты). Действие команды AND можно описать следующим образом: команда безусловно сбрасывает в 0 биты в тех позициях первого операнда, которые отмечены "нулями" в маске, оставляя прочие биты первого операнда неизменными.
- XOR — поразрядное исключающее ИЛИ, eXclusive OR (иногда на русском эту операцию называют "ЛИБО"). Эта двухоперандная команда фактически выполняет выборочное инвертирование битов. Например:
xor cl,0F0h ;Инвертирование битов старшей тетрады
Если исходно в cl содержалось 1101 10012, то после выполнения команды в cl будет содержаться 0010 10012 (отмечены проинвертированные биты). Действие команды xor можно описать так: команда инвертирует в первом операнде биты в позициях, которые отмечены в маске "единицами", оставляя прочие биты неизменными.
- TEST — проверка битовых полей. Команда чаще всего двухоперандная, выполняет поразрядное логическое умножение операндов и по результату операции изменяет состояние флагов "нуля" zf и "знака" sf, после чего результат операции теряется.
- NOT, COM — инвертирование операнда (замена значения каждого бита на противоположное). Это однооперандная команда.
Читайте также: