Побитовый сдвиг: О битовых операциях
Arduino Побитовый свдиг влево (>)
Описание
В C++ есть два оператора побитового сдвига: оператор сдвига влево << и оператор сдвига вправо >>. Эти операторы заставляют биты левого операнда сдвинуться влево или вправо на то количество позиций, которое указано во втором операнде.
Подробнее о двоичной математике см. здесь.
Синтаксис
переменная << количество_бит
переменная >> количество_бит
Параметры
переменная — (byte, int, long)
количество_бит — целое число <= 32
Пример:
int a = 5; // в двоичной системе: 0000000000000101
int b = a << 3; // в двоичной системе: 0000000000101000, или 40 в десятичной
int c = b >> 3; // в двоичной системе: 0000000000000101, или снова 5, как было изначально
Следует иметь ввиду, что при сдвиге значения x на y бит (x<),>
int a = 5; // в двоичной системе: 0000000000000101
int b = a << 14; // в двоичной системе: 0100000000000000 - первая 1 в 101 исчезла
Если вы уверены, что ни один из битов в сдвигаемом числе не пропадет, то для простоты можно считать, что оператор сдвига << умножает левый операнд на 2 в степени, показателем которой является правый операнд. Например, для получения степеней 2 могут быть использованы следующие выражения:
1 << 0 == 1
1 << 1 == 2
1 << 2 == 4
1 << 3 == 8
...
1 << 8 == 256
1 << 9 == 512
1 << 10 == 1024
...
Если вы сдвигаете x вправо на y бит (x>>y) и при этом старшим битом x является 1, то результат такой операции будеть зависеть от типа переменной x. Как уже отмечалось ранее, в переменных типа int старший бит является знаковым битом, определяющим является ли число положительным или отрицательным. Если переменная x имеет тип int, то при сдвиге x вправо знаковый бит копируется в младшие биты (по историческим причинам):
int x = -16; // в двоичной системе: 1111111111110000
int y = x >> 3; // в двоичной системе: 1111111111111110
Такое поведение называется расширением знака и, как правило, нежелательно: вместо единиц пользователь чаще ожидает увидеть нули в левой части x на месте свдинутых бит. В то же время для беззнаковых целых чисел (переменные типа unsigned int) действуют другие правила сдвига вправо. Поэтому для предотвращения копирования единиц в старших разрядах сдвигаемой переменной x, можно прибегнуть к преобразованию типов:
int x = -16; // в двоичной системе: 1111111111110000
int y = (unsigned int)x >> 3; // в двоичной системе: 0001111111111110
Таким образом, если предотвращать эффект расширения знака, оператор сдвига вправо >> можно использовать для деления числа на степени 2. Например:
int x = 1000;
int y = x >> 3; // целочисленное деление 1000 на 8, в результате которого y = 125.
Битовые операторы
Введение
Примеры
Побитовое И
&
Оператор выполнит двоичный И, где бит копируется , если она существует в обоих операндов. Это означает:
# 0 & 0 = 0
# 0 & 1 = 0
# 1 & 0 = 0
# 1 & 1 = 1
# 60 = 0b111100
# 30 = 0b011110
60 & 30
# Out: 28
# 28 = 0b11100
bin(60 & 30)
# Out: 0b11100
Побитовое ИЛИ
|
Оператор выполнит двоичное «или», где бит копируется, если он существует в любом из операндов. Это означает:
# 0 | 0 = 0
# 0 | 1 = 1
# 1 | 0 = 1
# 1 | 1 = 1
# 60 = 0b111100
# 30 = 0b011110
60 | 30
# Out: 62
# 62 = 0b111110
bin(60 | 30)
# Out: 0b111110
Побитовое XOR (исключающее ИЛИ)
^
Оператор будет выполнять двоичный XOR , в котором двоичный 1
копируется тогда и только тогда , когда это значение ровно один операнд. Другой способ задания этого является то , что результат 1
только если операнды разные. Примеры включают в себя:
# 0 ^ 0 = 0
# 0 ^ 1 = 1
# 1 ^ 0 = 1
# 1 ^ 1 = 0
# 60 = 0b111100
# 30 = 0b011110
60 ^ 30
# Out: 34
# 34 = 0b100010
bin(60 ^ 30)
# Out: 0b100010
Побитовый сдвиг влево
<<
оператор выполняет побитовое «сдвиг влево» , где значение левого операнда перемещается влево на число битов данных в правом операнде.
# 2 = 0b10
2 << 2
# Out: 8
# 8 = 0b1000
bin(2 << 2)
# Out: 0b1000
Выполнение левого разрядное смещение 1
эквивалентно умножению на 2
:
7 << 1
# Out: 14
Выполнение левого разрядного смещения n
эквивалентно умножения на 2**n
:
3 << 4
# Out: 48
Побитовый сдвиг вправо
>>
оператор выполняет побитовое «сдвиг вправо» , где значение левого операнда перемещается вправо на число битов данных в правом операнде.
# 8 = 0b1000
8 >> 2
# Out: 2
# 2 = 0b10
bin(8 >> 2)
# Out: 0b10
Выполнение правильного битового смещения 1
эквивалентно целочисленного деления на 2
:
36 >> 1
# Out: 18
15 >> 1
# Out: 7
Выполнение правильного битового смещения n
эквивалентно целочисленное деление на 2**n
:
48 >> 4
# Out: 3
59 >> 3
# Out: 7
Побитовое НЕ
~
Оператор переворачивает все биты числа. Поскольку компьютеры используют прямой код — прежде всего, в дополнении до двух обозначений для кодирования отрицательных двоичных чисел , где отрицательные числа записываются с ведущим один (1) вместо ведущего нуля (0).
Это означает , что если вы используете 8 бит для представления номера вашего дополнительного кода комплемента, вы бы относиться к модели от 0000 0000
до 0111 1111
для представления чисел от 0 до 127 и резервного 1xxx xxxx
для представления отрицательных чисел.
Восьмиразрядные числа с двумя дополнительными числами
Биты Значение без знака Значение двух дополнений 0000 0000 0 0 0000 0001 1 1 0000 0010 2 2 0111 1110 126 126 0111 1111 127 127 1000 0000 128 -128 1000 0001 129 -127 1000 0010 130 -126 1111 1110 254 -2 1111 1111 255 -1
По существу, это означает , что в то время как 1010 0110
имеет беззнаковое значение 166 (прибыл в путем добавления (128 * 1) + (64 * 0) + (32 * 1) + (16 * 0) + (8 * 0) + (4 * 1) + (2 * 1) + (1 * 0)
), оно имеет значение дополнительного код дополнение -90 (прибыли в добавлении (128 * 1) - (64 * 0) - (32 * 1) - (16 * 0) - (8 * 0) - (4 * 1) - (2 * 1) - (1 * 0)
, и дополняя значение).
Таким образом, отрицательные числа в диапазоне до -128 ( 1000 0000
). Ноль (0) представляется в виде 0000 0000
, и минус один (-1) , как 1111 1111
.
В целом, однако, это означает , ~n = -n - 1
.
# 0 = 0b0000 0000
~0
# Out: -1
# -1 = 0b1111 1111
# 1 = 0b0000 0001
~1
# Out: -2
# -2 = 1111 1110
# 2 = 0b0000 0010
~2
# Out: -3
# -3 = 0b1111 1101
# 123 = 0b0111 1011
~123
# Out: -124
# -124 = 0b1000 0100
Обратите внимание, что общий эффект этой операции при нанесении на положительные числа можно суммировать:
~n -> -|n+1|
И затем, применительно к отрицательным числам, соответствующий эффект:
~-n -> |n-1|
Следующие примеры иллюстрируют это последнее правило …
# -0 = 0b0000 0000
~-0
# Out: -1
# -1 = 0b1111 1111
# 0 is the obvious exception to this rule, as -0 == 0 always
# -1 = 0b1000 0001
~-1
# Out: 0
# 0 = 0b0000 0000
# -2 = 0b1111 1110
~-2
# Out: 1
# 1 = 0b0000 0001
# -123 = 0b1111 1011
~-123
# Out: 122
# 122 = 0b0111 1010
Операции на месте
Все операторы Побитового (кроме ~
) имеет свои собственные места версии
a = 0b001
a &= 0b010
# a = 0b000
a = 0b001
a |= 0b010
# a = 0b011
a = 0b001
a <<= 2
# a = 0b100
a = 0b100
a >>= 2
# a = 0b001
a = 0b101
a ^= 0b011
# a = 0b110
Синтаксис
Параметры
Примечания
Начинаем изучать STM32: битовые операции / Хабр
Небольшое отступление…
В прошлом уроке мы рассмотрели с чего начать, если вы решили изучать микроконтроллеры STM32: как настроить IDE, как создать простой проект, как откомпилировать программу и как запустить программу на выполнение. После полюбовались на перемигивание светодиодов на Discovery-плате )
Начиная новую статью, я задумывал сразу же перейти к подробному разбору листинга программы, который заставлял попеременно перемигиваться наши светодиоды, но уже перейдя к написанию, я вдруг осознал для себя, что есть большое количество вопросов без ответа на которые — перейти к рассмотрению программы было бы преждевременно. И для себя я определил целый перечень таких вопросов:
- Что же такое битовые операции? Как ими пользоваться?
- Что такое регистры и как они связаны с битовыми операциями?
- Из чего состоят микроконтроллеры STM32F0xx-серии, как осуществляется тактирование и чем обеспечена жизнь внутри МК?
- Как происходит стартовая инициализация МК, зачем нужен startup-файл, что делает функция SystemInit? Объяснение на пальцах.
- Из чего состоит библиотека CMSIS? Как в ней ориентироваться? Что полезного можно из нее извлечь и как ей пользоваться?
Именно с рассмотрения этих вопросов я хотел бы продолжить повествование о программировании STM32.
Список статей:
- Начинаем изучать STM32 или Управляем светом по-умному
- Начинаем изучать STM32: битовые операции
- Начинаем изучать STM32: Что такое регистры? Как с ними работать?
Основные логические операции
Только начиная изучать микроконтроллеры, слова «регистр» и «битовые операции» для меня казались чем-то таинственно загадочным и я долго не хотел переходить к рассмотрению данной темы. Но когда я более-менее разобрался с тем, что это такое я понял что зря откладывал изучение такой важной темы в дальний ящик. Битовые операции наверное самые распространенные операции в микроконтроллере и знание того, как и зачем их можно применять в нашей работе — откроет перед нами огромный потенциал возможностей для управления всем и вся в нашем МК!
Все мы на уроках информатики в школе знакомились с тем, что такое цифровая техника, почему она так называется, какие существуют основные логические операции.Все современные цифровые технологии основаны на двоичной математике и логических схемах.
Микроконтроллер всегда оперирует только двумя состояниями: «ноль» — нет напряжения, «единица» — есть напряжение. Давайте немного освежим в голове знания о основных логических операциях т.к. они составляют основу всей цифровой техники.
- Конъюнкция — обозначается как «Логическое И» или «Логическое умножение». В сущности, результат от выполнения данной логической операции двух для выражений А и В подобен их умножению. То есть, выражение примет значение «1» в случае только если и А, и В имеют значение «1». Во всех других случаях будет значение «0». Может обозначаться как И, &&, AND, &
- Дизъюнкция — обозначается как «Логическое ИЛИ» или «Логическое сложение». Результат от выполнения данной логической операции двух для выражений А и В подобен их сложению. То есть, выражение примет значение «1» в случае если хотя бы одно из выражений А и В имеют значение «1». Может обозначаться как ИЛИ, ||, OR, |.
- Инверсия — обозначается как «Логическое НЕ» или «Отрицание». Результат от выполнения данной логической операции двух для выражения А равен противоположному. То есть, выражение примет значение 1 в случае если выражение А равно 0 и наоборот. Может обозначаться как НЕ, !, NOT, ~.
- Строгая дизъюнкция — обозначается как «Исключающее ИЛИ» или «Логическое сложение, исключающее ИЛИ». Результат от выполнения данной логической операции двух для выражений А и В примет значение 1 в случае если А и В имеют разные значения. Может обозначаться как Искл. ИЛИ, XOR, ^.
Битовые операции
Битовые операции — практически то же самое, что и логические операции только лишь с той разницей, что применяются они к битам и к числам двоичной системы.
К слову говоря, для простоты изучения битовых операций я использовал программу 32-bit ASM Calculator от ManHunter. С помощью данной программы можно проверять результаты выполнения битовых операций, переводить числа из одной системы счисления в другую. Программа имеет интуитивно понятный интерфейс и после знакомства программа стала одним из основных инструментов в моей работе с микроконтроллерами. Небольшое пояснение к интерфейсу программы данно на изображении ниже:
Битовая операция «НЕ» — «~»
Если бит равен «1», то после выполнения операции «НЕ» он будет равен «0», и наоборот. Операция сразу же выполняется над всеми битами двоичного числа. Например, инвертируем число FF:
Битовая операция «И» — «&»
Если оба бита в разряде равны «1», то после выполнения операции «И» результат в разряде будет равен «1», но если хотя бы один из битов равен «0» тогда и результат будет равен «0». Операция так же выполняется поразрядно. Например, «умножим» два числа 0xFF0 и 0xF0F:
В результате мы увидим, что в тех разрядах где были единицы в обоих числах, в результате получились единицы, во всех остальных случаях — нули.
Рассмотрим варианты практического применения:
- В ситуации, если нам необходимо сбросить конкретный бит или группу битов в ноль мы можем использовать маску. Думаю, будет нагляднее показать это на примере. Допустим, мы берем число и 0xF8F и нам надо чтобы 7-й бит стал вместо единицы нулем. Нет проблем, накидываем маску и снимаем галочку с нужного бита. Умножаем числа и получаем результат:
- Если нам необходимо проверить конкретный бит в числе на 0 или 1 — мы так же используя маску проводим умножение. В маске мы устанавливаем бит, который хотели бы проверить. Если требуемый бит равен «0» — то результатом вычисления будет «0», если «1» то, соответственно, «1». Если мы хотим узнать, равен ли 7-й бит единицы — делаем соответствующую маску и умножаем наше число на маску. Все просто:
Если нам нужно проверить четность числа(имеется ввиду способность числа делиться на два) — то мы таким же образом проверяем 1-й бит, если он равен «1» — то число нечетное, если там «0» то число четное. Попробуйте сами, в целях обучения и формирования навыков, сделать данную проверку.
Битовая операция «ИЛИ» — «|»
Если один или оба из пары битов равен «1» то результат будет «1», иначе если оба бита равны «0» то результат будет равен «0». То есть, грубо говоря, производится сложение всех единиц в разрядах. Например если мы складываем два числа 0xF8F и 0x7F, то получим следующий результат:
Рассмотрим вариант практического применения:
- Если нам необходимо установит конкретный бит в числе на 1 — мы так же используя маску проводим сложение. Например, чтобы выставить 15-й бит в числе 0xFF0 нужно провести операцию логического сложения и мы получим требуемый результат:
Попробуйте самостоятельно поиграться с различными числами и понаблюдать за результатами.
Битовая операция «ИСКЛЮЧАЮЩЕЕ ИЛИ» — «^»
Если биты в разряде отличаются и не равны тогда результат будет «1», иначе «0». Например, если мы делаем XOR числа 0xF8F и 0x7F, то мы увидим что в разрядах в которых находятся отличные биты то там в результате получается «1» и в местах где биты одинаковые, будь то «0» или «1» — получился «0», в итоге мы получим следующий результат:
Рассмотрим варианты практического применения:
- Если нам понадобилось инвертировать какие-либо биты в числе, можно используя маску с легкостью сделать это используя операцию XOR. Давайте сделаем инверсию 6 и 7 разряда в числе 0xF8 используя маску 0xC0. Результат вы можете посмотреть на изображении:
- Бывают ситуации когда необходимо сравнить два регистра и определить равны они или нет. В этом случае нам необходимо значения регистров подвергнуть операции XOR. Если результат получился «0» — тогда регистры равны, иначе — не равны:
Битовые операции сдвига
Существует ряд интересных и порой чрезвычайно полезных битовых операций именуемых как операции сдвига. Двигать разряды можно как вправо, так и влево. В ходе данной операции происходит сдвиг всех разрядов двоичного числа на указанное количество позиций, при этом, в случае если сдвиг идёт влево — старший бит (самый левый) теряется, а в младший (самый правый) записывается «0». При логическом сдвиге вправо происходит обратная ситуация — младший бит (самый правый) теряется, а в старший записывается «0». Дополнительно хотелось бы отметить, что в случае 32-разрядных слов сдвигаются все 32 разряда целиком. Рассмотрим операции сдвига подробнее.
Cдвиг влево — «<<«
То, как происходит сдвиг вы можете увидеть на изображении ниже. Думаю, что всё достаточно очевидно:
При двоичном сдвиге можно заметить одну интересную особенность. Сдвиг на один разряд умножает наше число на 2. Если сдвинуть на n разрядов наше число x то получится x * (2 * n). Попробуйте самостоятельно отследить эту закономерность через нашу утилку для подсчета. =)
Cдвиг вправо — «>>»
То, что получается в результате сдвига вправо достаточно наглядно отражено на изображении:
При двоичном сдвиге вправо можно заметить что происходит ситуация обратная сдвигу влево — число делится на 2 с при сдвиге в 1 разряд и после на 2 * n, где n — количество разрядов на которые произведен сдвиг. Так же попробуйте самостоятельно поиграться с числами и которые заведомо делятся на 2 нацело. И вопрос на засыпку — какой результат будет если вы поделите таким образом нечетное число?
Важное замечание. Если вы будете делать сдвиг для переменной с отрицательным знаком (signed) — освободившиеся позиции будут заполняться единичками.
В качестве заключения…
Многим начинающим данная тема может показаться дико скучной и может сложиться ощущение что ну вообще не понятно где и как можно применить эти знания. Спешу вас обнадежить, в ситуациях когда нужно поднять ту или иную ногу МК или записать параметр в какой-нить периферийный блок или модуль — там кругом и всюду будут требоваться знания битовых операций. Так как статья получилась достаточно объемной, рассмотрение регистров мы перенесем на следующий урок. Ну и в последующем можно использовать эту статью как шпаргалку.
В качестве домашнего задания попробуйте самостоятельно разобрать код нашей программы в блоке while(1) {… } и понять как же битовыми операциями мы включаем и выключаем наши светодиоды. Ну а на следующем уроке я расскажу как оно происходит на самом деле!
Список статей:
- Начинаем изучать STM32 или Управляем светом по-умному
- Начинаем изучать STM32: битовые операции
- Начинаем изучать STM32: Что такое регистры? Как с ними работать?
Команды сдвига — Побитовая обработка
В программировании сдвигом называют одновременное перемещение границ расположения некоторой информации. Здесь можно провести хорошую аналогию с перемещениями, возникающими вследствие умножения или деления числа на какую-либо степень двойки. Пусть, например, некоторый байт содержит число 001000102. Сдвиг байта влево на 1 бит означает одновременное смещение всех его битов влево на 1 позицию.
Справа в освобождающийся разряд записывается 0. Первоначальное значение старшего разряда (разряда 0) теряется. Заметим, что, умножив исходное содержимое байта на 2, мы получили бы тот же результат.
Аналогично выполняются любые другие сдвиги. Рассмотрим в качестве еще одного примера сдвиг байта 10101110г на 3 разряда вправо.
В данном случае освободившиеся разряды располагаются в левом конце числа, содержимое же разрядов 5,6,7 утеряно. Заметим, что сдвиг не эквивалентен делению, если рассматривать содержимое байта как целое со знаком. Это очевидно, так как исходное число отрицательно, а результат положителен.
В ЭВМ Систем 360 и 370 возможны два типа сдвигов: арифметические и логические. Разница между ними заключается в обращении с содержимым знакового разряда. Сдвиги арифметического типа позволяют устранить возникшую в нашем последнем примере проблему сдвига знакового бита. Эти сдвиги обычно используются при обработке арифметической информации. Логические сдвиги выполняются так, как это и было описано выше, знаковый разряд в данном случае ничем не отличается от остальных.
Приведенные выше примеры касались сдвигов содержимого отдельных байтов. Необходимо отметить, что во всех ЭВМ Систем 360 и 370 все команды сдвига оперируют над содержимым регистров.
Логические сдвиги
Логические сдвиги проще арифметических: освободившиеся разряды всегда заполняются нулями, и знаковый бит не требует особого обращения. Вследствие этого логические сдвиги используются не для обработки арифметической информации, а для организации более компактной записи некоторых данных. Выполнение команд логического сдвига не оказывает влияния на признак результата.
Начнем наше рассмотрение с примера. Пусть содержимое регистра 5 в двоичной форме записывается как
10 1000 0111 0010 1001 1100 1111 0110
Команда
SLL 5,6
(Shift Left Logical — СДВИГ ВЛЕВО КОДА) производит сдвиг содер¬жимого регистра 5 на 6 разрядов влево. Результат ее выполнения вы-
глядит так:
(5)=ООО11100101001110011110110000000
формат команд сдвига является модификацией формата RS. Как обычно, первый операнд указывает регистр. Содержимое этого регистра (или регистров) будет сдвинуто в процессе выполнения команды. В обычных командах формата RS вторым операндом является адрес области памяти. Однако в командах сдвига этот операнд не используется для адресации. В качестве второго операнда выступает S-адрес, использующийся в данном случае не по своему обычному назначению. Последние 6 битов суммы
D2+(B2)
показывают, на какое количество разрядов должен быть произведен сдвиг. Содержимое регистра может быть сдвинуто на указываемое таким образом количество разрядов вправо или влево.
|
|
|
|
|
|
Команды логического сдвига обычно используются для придания двоичной информации более компактной формы. Например, чтобы запомнить последовательность, состоящую из 100 чисел в форме полных слов, требуется 3200 битов памяти. Если известно, что все числа положительные и не превышают 64, то для хранения каждого числа на самом деле оказывается достаточно 6 битов, всего 600 битов для всей последовательности. (Если быть более точными, то при хранении 5 чисел в каждом полном слове потребуется всего 640 битов.) На рис. 14.4 изображен программный сегмент, выполняющий упаковку 5 таких чисел, первоначально находящихся в последовательных словах памяти, в регистр 7. Перед записью каждого следующего числа необходимо предварительно сдвинуть содержимое регистра 7 влево на шесть разрядов с тем, чтобы освободить место для вновь записываемого числа. Непосредственная запись может быть произведена с помощью команды О (ИЛИ). После ее выполнения число оказывается в последних шести разрядах регистра.
Рис. 14.4. Размещение в регистре 7 пяти 6-битовых чисел, расположенных в полных словах памяти, начиная с адреса NMBRS.
При проведении обратного преобразования (т. е. при переводе данных из компактной формы в обычную) удобно использовать сдвиг содержимого одного регистра в другой. Для этого предусмотрены две команды двойного сдвига: SLDL (Shift Left Double Logical — СДВИГ ВЛЕВО ДВОЙНОЙ КОДА) и SRDL (Shift Right Double Logical — СДВИГ ВПРАВО ДВОЙНОЙ КОДА).
|
|
|
|
|
|
Здесь R1 на самом деле является ссылкой сразу на два регистра, R1 и R1 + 1. R1 при этом должен быть четным. При выполнении двойных сдвигов 64-разрядное содержимое двух регистров рассматривается как единое число. При левом сдвиге теряются старшие биты R1. Старшие биты R1 +1 занимают места в правом конце R1. Освобождающимися в данном случае являются младшие разряды R1 + 1.
Пусть регистры 4 и 5 содержат соответственно
(4) =0011 ООП ООН 0101 0110 0111 1000 1001
(5) = 1100 1011 1010 1001 1000 0111 0110 0101
По команде
SLDL 4,7
производится сдвиг содержимого регистров 4 и 5 влево на 7 разрядов. При этом теряются 7 старших разрядов регистра 4, содержимое 7 старших разрядов регистра 5 перемещается в 7 крайних правых разрядов регистра 4, и, наконец, 7 младших разрядов регистра 5 освобождаются и заполняются нулями. Итак, окончательно получается:
Двойной сдвиг вправо выполняется совершенно аналогично. Теряется содержимое младших разрядов R1 + 1. Биты из младших разрядов R1 попадают в старшие разряды R1 + 1. И, наконец, старшие разряды R1, освобождаясь, заполняются нулями.
Как уже упоминалось, двоичные сдвиги используются для «распаковки» двоичной информации. Предположим, что из слова BITDATA требуется выделить число, расположенное в битах 13—18, и затем записать его уже в обычной форме по адресу BITS. Приводимая ниже последовательность команд обеспечивает выполнение требуемых действий.
L 11,BITDATA
SLDL 10,13
LA 10,0
SLDL 10,5
ST 10,BITS
На рис. 14.5 приведен программный сегмент, предназначенный для «распаковки» содержимого регистра 7 (см. программу рис. 14.4) и записи результатов в форме полных слов последовательно, начиная со слова NMBRS.
Арифметические сдвиги
Мы уже знаем, что команды сдвига могут, вообще говоря, служить для умножения и деления чисел на степени двойки. Однако при этом могут возникнуть некоторые трудности со знаковым разрядом. Пусть, например,
(9) =0000 1000 ООП 1101 0111 0010 0100 0010
Рис. 14.5. Размещение пяти 6-битовых чисел, находящихся в регистре 7, в последовательных словах памяти, начиная с адреса NUMBRS.
Выполнение команды
SLL 9,3
в данном случае эквивалентно умножению на 23=8, так как в результате получается
(9)=0100 0001 1110 1011 1001 0010 0001 0000
Однако если, употребляя ту же команду, произвести сдвиг влево на 4 разряда, то, очевидно, мы получим
(9) = 1000 ООП 1101 0111 0010 0100 0110 0000
Итак, если следовать обычным правилам определения знака числа, то выйдет, что умножение на 16 может изменить знак числа (первоначальное содержимое регистра 9 было положительно, тогда как в результате нами получено число с противоположным знаком).
Устранить возникшие трудности можно с помощью команд арифметического сдвига. Арифметические сдвиги тем отличаются от логических, что при их выполнении содержимое знакового разряда сохраняется для обеспечения возможности дальнейшего нормального выполнения арифметических операций. Арифметический сдвиг не затрагивает знаковый бит. При сдвиге вправо разряды освобождаются, начиная с первого (знаковый разряд имеет номер 0). После выполнения сдвига в каждый из освободившихся разрядов заносится знаковый бит. Если, например, исходное число было положительным (его знаковый бит был равен 0), то при арифметическом сдвиге вправо освобождающиеся старшие разряды заполняются нулями. Если же исходное число было отрицательным, то происходит заполнение не нулями, а единицами. Проиллюстрируем сказанное на примере. Пусть сначала
(11)=0001 0010 0011 0100 0101 0110 0111 1000
Побитовые операции
Побитовые операторы JavaScript:
Оператор | Название | Описание |
---|---|---|
& | И | Возвращает 1, если оба бита равны 1 |
| | ИЛИ | Возвращает 1, если хотя бы один из двух битов равен 1 |
^ | ИСКЛЮЧАЮЩЕЕ ИЛИ | Возвращает 1, если только один из двух битов равен 1, но не оба |
~ | НЕ | Инвертирует все биты |
<< | Побитовый сдвиг влево | Сдвиг влево с заполнением появившихся младших (справа) битов нулями |
>> | Побитовый сдвиг вправо со знаком | Сдвиг вправо с копированием знака (арифметический сдвиг вправо). Пустые биты заполняются копией крайнего левого бита |
>>> | Побитовый сдвиг вправо | Сдвиг вправо с заполнением появившихся старших (слева) битов нулями |
Примеры:
Операция | Результат | То же, что | Результат |
---|---|---|---|
5 & 1 | 1 | 0101 & 0001 | 1 |
5 | 1 | 5 | 0101 | 0001 | 101 |
5 ^ 1 | 4 | 0101 ^ 0001 | 100 |
~5 | 10 | ~0101 | 1010 |
5 << 1 | 10 | 0101 << 1 | 1010 |
5 >> 1 | 2 | 0101 >> 1 | 10 |
5 >>> 1 | 2 | 0101 >>> 1 | 10 |
Числовые значения в JavaScript хранятся как 64 битные числа с плавающей точкой. Однако все побитовые операции выполняются с 32 битными двоичными числами.
Перед выполнением побитовой операции JavaScript преобразует числовые операнды в 32 битные целые числа со знаком. После завершения побитовой операции результат преобразуется обратно в 64 битное число.
В примерах в таблице выше приведены 4-битные числа без знака. Поэтому ~5 возвращает 10.
В действительности же JavaScript использует 32-битные числа со знаком. Таким образом, в JavaScript выражение ~ 5 вернет не 10, а -6:
00000000000000000000000000000101 (5)
11111111111111111111111111111010 (~5 = -6)
В целых числах со знаком самый левый бит используется для указания знака.
Побитовое И (AND)
Если побитовое И (AND) выполняется с парой бит, то 1 возвращается тогда, когда оба бита равны 1.
Пример с 1-битовыми числами:
Операция | Результат |
---|---|
0 & 0 | 0 |
0 & 1 | 0 |
1 & 0 | 0 |
1 & 1 | 1 |
Пример с 4-битовыми числами:
Операция | Результат |
---|---|
1111 & 0000 | 0 |
1111 & 0001 | 1 |
1111 & 0010 | 10 |
1111 & 0100 | 100 |
Побитовое ИЛИ (OR)
Если побитовое ИЛИ (OR) выполняется с парой бит, то 1 возвр
Побитовый сдвиг — это… Что такое Побитовый сдвиг?
Би́товый сдвиг — изменение позиций битов в слове на одну и ту же величину.
В основной своей массе компьютеры не могут напрямую адресовать биты, которые содержатся группами по 8, 16, 32 битов в словах. Для обеспечения работы с битами существует множество команд, к которым относятся и сдвиги: Все сдвиги похожи друг на друга поведением средних битов: они просто сдвигаются влево или вправо на определённую величину. И различаются поведением крайних битов: одного, который уходит из слова, и второго, который должен появиться в слове.
Логический сдвиг
Логический сдвиг влево | Логический сдвиг вправо |
Сдвиг, при котором уходящий бит уходит, не влияя на оставшееся биты, а на место появившегося бита записывается бит 0.
Пример работы операции сдвига:
- Пусть у нас есть число 10101010b (в двоичной системе).
- Если сделать сдвиг влево на 1 бит, то получим число 01010100b
- Если сделать сдвиг вправо на 1 бит, то получим число 01010101b
В большинстве процессоров уходящий бит сохраняется в флаге переноса. Эта функция широко используется при работе с многобайтовыми числами.
Арифметический сдвиг
Арифметический сдвиг влево | Арифметический сдвиг вправо |
При этом сдвиге слово рассматривается не просто как группа битов, а как целое число в дополнительном коде. При сдвиге влево ведёт себя как логический сдвиг, при сдвиге вправо: уходящий бит уходит, не влияя на оставшееся биты, а на место появившегося бита устанавливается бит, соответствующий знаку.
Пример работы операции сдвига:
- Пусть у нас есть число 11111010b=−6 (в двоичной системе).
- Если сделать сдвиг влево на 1 бит, то получим число 11110100b=−12
- Если сделать сдвиг вправо на 1 бит, то получим число 11111101b=−3
Легко заметить, что при арифметическом сдвиге сдвиг влево соответствует умножению на 2, а сдвиг вправо делению на 2 (в общем случае — на основание системы счисления). Исключение: −1 >>a 1 = −1
(в общем случае это относится к числам от −1 до −p+1, где p — основание системы счисления).
Схемотехническая реализация операций сдвига очень проста. Именно поэтому эти операции рекомендуют использовать для операций умножения и деления целых чисел на числа равные степени 2 (2, 4, 8, 16, 32, 64 и т. д.).
Циклический сдвиг
Циклический сдвиг влево | Циклический сдвиг вправо |
При этом сдвиге уходящий бит появляется на месте появившегося.
Пример работы операции сдвига:
- Пусть у нас есть число 11111010b (в двоичной системе).
- Если сделать сдвиг влево на 1 бит, то получим число 11110101b
- Если сделать сдвиг вправо на 1 бит, то получим число 01111101b
Циклический сдвиг через бит переноса
Циклический сдвиг влево через бит переноса | Циклический сдвиг вправо через бит переноса |
В архитектуру многих процессоров входит флаг переноса в следующий разряд (например, cf
на n+1)-битным числом, состоящим из регистра и флага переноса.
Например, если у нас в регистре число 11111010b, флаг переноса равен 0:
- После сдвига влево на 1 бит: в регистре 11110100b, флаг переноса равен 1
- После сдвига вправо на 1 бит: в регистре 01111101b, флаг переноса равен 0
Операция циклического сдвига через бит переноса используется при работе с многобайтовыми числами. В частности, чтобы сдвинуть вправо на 1 бит длинное число, нужно очистить[1]cf
(в случае деления числа со знаком нужно записать в cf
старший бит старшего слова) и циклически сдвинуть на единицу через cf
каждое слово, начиная с верхнего. Например, пусть у нас есть число 011000111100b, занимающее три 4-битных слова:
Было: HI=0110, MED=0011, LO=1100, cf=0 После сдвига HI: HI=0011, MED=0011, LO=1100, cf=0 После сдвига MED: HI=0011, MED=0001, LO=1100, cf=1 После сдвига LO: HI=0011, MED=0001, LO=1110, cf=0
Сдвиги через регистр флагов более чем на 1 бит практически не используются.
Примечания
- ↑ Можно вместо очистки флага для первого обрабатываемого слова использовать арифметический\логический сдвиг, если он присваивает флагу
cf
значение вышедшего бита.
Источник
Wikimedia Foundation.
2010.
Битовый сдвиг — это… Что такое Битовый сдвиг?
Би́товый сдвиг — изменение позиций битов в слове на одну и ту же величину.
Большинство компьютеров не могут напрямую адресовать биты, которые содержатся группами по 8, 16, 32 или 64 битов в словах. Для обеспечения работы с битами существует множество машинных инструкций, включающие различные типы сдвигов. Все сдвиги похожи друг на друга поведением средних битов, которые просто сдвигаются влево или вправо на определённую величину. Однако, поведение крайних битов, которые уходят из слова и которые появляются в слове, зависит от типа сдвига.
В электронике битовые сдвиги осуществляются в регистрах сдвига.
Логический сдвиг
Логический сдвиг влево | Логический сдвиг вправо |
Сдвиг, при котором уходящий бит уходит, не влияя на оставшееся биты, а на место появившегося бита записывается бит 0.
Пример работы операции сдвига:
- Пусть у нас есть число 10101010b (в двоичной системе).
- Если сделать сдвиг влево на 1 бит, то получим число 01010100b
- Если сделать сдвиг исходного числа вправо на 1 бит, то получим число 01010101b
В большинстве процессоров уходящий бит сохраняется во флаге переноса. Эта функция широко используется при работе со многобайтовыми числами.
Арифметический сдвиг
Арифметический сдвиг влево | Арифметический сдвиг вправо |
При этом сдвиге слово рассматривается не просто как группа битов, а как целое число в дополнительном коде. При сдвиге влево ведёт себя как логический сдвиг, при сдвиге вправо: уходящий бит уходит, не влияя на оставшиеся биты, а на место появившегося бита устанавливается бит, соответствующий знаку.
Пример работы операции сдвига:
- Пусть у нас есть число 11111010b = −6 (в двоичной системе).
- Если сделать сдвиг влево на 1 бит, то получим число 11110100b = −12
- Если сделать сдвиг исходного числа вправо на 1 бит, то получим число 11111101b = −3
Легко заметить, что при арифметическом сдвиге сдвиг влево соответствует умножению на 2, а сдвиг вправо — делению на 2 (в общем случае — на основание системы счисления) с округлением к −∞. Например:
1011 = −5 1111 = −1 >>a 1 >>a 1 ---- ---- 1101 = −3 1111 = −1
Схемотехническая реализация операций сдвига очень проста. Именно поэтому эти операции рекомендуют использовать для операций умножения и деления целых чисел на числа, равные степени 2 (2, 4, 8, 16, 32, 64 и т. д.) — если, конечно, такое округление отрицательных чисел не мешает.
Циклический сдвиг
Циклический сдвиг влево | Циклический сдвиг вправо |
При этом сдвиге уходящий бит появляется на месте появившегося.
Пример работы операции сдвига:
- Пусть у нас есть число 11111010b (в двоичной системе).
- Если сделать сдвиг влево на 1 бит, то получим число 11110101b
- Если сделать сдвиг вправо на 1 бит, то получим число 01111101b
Циклический сдвиг через бит переноса
Циклический сдвиг влево через бит переноса | Циклический сдвиг вправо через бит переноса |
В архитектуру многих процессоров входит флаг переноса в следующий разряд (например, cf
на x86). Данная операция выполняет циклический сдвиг над (n+1)-битным числом, состоящим из регистра и флага переноса.
Например, если у нас в регистре число 11111010b, флаг переноса равен 0:
- После сдвига влево на 1 бит: в регистре 11110101b, флаг переноса равен 1
- После сдвига вправо на 1 бит: в регистре 01111101b, флаг переноса равен 0
Операция циклического сдвига через бит переноса используется при работе с многобайтовыми числами. В частности, чтобы сдвинуть вправо на 1 бит длинное число, нужно очистить[1]cf
(в случае деления числа со знаком нужно записать в cf
старший бит старшего слова) и циклически сдвинуть на единицу через cf
каждое слово, начиная с верхнего. Например, пусть у нас есть число 011000111100b, занимающее три 4-битных слова:
Было: HI=0110, MED=0011, LO=1100, cf=0 После сдвига HI: HI=0011, MED=0011, LO=1100, cf=0 После сдвига MED: HI=0011, MED=0001, LO=1100, cf=1 После сдвига LO: HI=0011, MED=0001, LO=1110, cf=0
Сдвиги через регистр флагов более чем на 1 бит практически не используются.
См. также
Примечания
- ↑ Можно вместо очистки флага для первого обрабатываемого слова использовать арифметический\логический сдвиг, если он присваивает флагу
cf
значение вышедшего бита.
Ссылки
vbscript — Битовый сдвиг при отсутствии … битового сдвига оператора
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.Сборка
— переменный сдвиг бит
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.
битовый сдвиг — это … Что такое битовый сдвиг?
битовый сдвиг — существительное Побитовая операция, при которой биты в значении сдвигаются влево или вправо… Викисловарь
Shift — обычно означает изменение (положение). Сдвиг может означать: * Переключение передач для переключения передач в автомобиле * Сменная работа, практика работы * Сдвиг (музыка), изменение уровня музыки * Сдвиг (журнал), бывшие канадские технологии и культура…… Википедия
Shift — Steht für: die Umschalttaste beziehungsweise Hochstelltaste auf Tastaturen Schiften beim Segeln in der Fotografie als Shift Effekt, um.
Битовый массив — Битовый массив (или битовая карта, в некоторых случаях) представляет собой структуру данных массива, в которой компактно хранятся отдельные биты (логические значения).Он реализует простую структуру данных набора, хранящую подмножество {1,2, …, n}, и эффективен при использовании битового уровня…… Wikipedia
Битовое поле — Битовое поле — это распространенная идиома, используемая в компьютерном программировании для компактного хранения набора флагов логического типа данных в виде последовательности битов. Битовое поле хранится в виде целого типа известной фиксированной битовой ширины. Каждый логический флаг хранится в отдельном…… Wikipedia
Битовая корзина — Битовая корзина — это жаргонный термин, обозначающий место потери компьютеризированных данных любым способом; любые данные, которые не попадают туда, где должны, потеряны при передаче, компьютерный сбой и т.п., считаются отправленными в битовое ведро mdash; это… Википедия
Shift JIS — (также SJIS, MIME-имя Shift JIS) — это кодировка символов для японского языка, первоначально разработанная японской компанией ASCII Corporation совместно с Microsoft и стандартизированная как JIS X 0208, приложение 1.Он основан на…… Википедии
Shift 2: Unleashed — Европейский разработчик обложек Slightly Mad Studios Издатель (ы) Electronic Arts… Википедия
Bit-banging — это метод последовательной связи с использованием программного обеспечения вместо специального оборудования, такого как UART или сдвиговый регистр. Программная процедура обрабатывает функцию передачи UART путем чередования контактов микроконтроллера с заданными интервалами времени. А…… Википедия
смена — с.m.inv. ES англ. {{wmetafile0}} ТС информирует. 1. nelle tastiere dei calcolatori elettronici, tasto, generalmente contrassegnato da una freccia rivolta verso l alto, che consente di scrivere in maiuscolo le single lettere or di scrivere il carattere… Dizionario italiano
Регистр сдвига — В цифровых схемах регистр сдвига представляет собой группу триггеров, настроенных линейным образом, входы и выходы которых соединены вместе таким образом, что данные смещаются вниз по строке при активации схемы .Регистры сдвига…… Википедия
.