7. Чем отличается логический сдвиг двоичного кода от арифметического сдвига?
При логическом сдвиге значение последнего бита по направлению сдвига теряется (копируясь в бит переноса), а первый приобретает нулевое значение.
Арифметический сдвиг аналогичен логическому, но число считается знаковым, представленным в дополнительном коде. Так, при правом сдвиге старший бит сохраняет своё значение. Левый арифметический сдвиг идентичен логическому.

Арифметический сдвиг:
Вывод: арифметический сдвиг отличается от логического тем, что он не изменяет значение старшего бита, и предназначен для чисел со знаком.
8. Как изменяется значение числа при арифметическом сдвиге на 1 двоичный разряд влево?
При арифметическом сдвиге сдвиг влево соответствует умножению на 2 (в общем случае — на основание системы счисления).
9. Как изменяется значение числа при арифметическом сдвиге на 1 двоичный разряд вправо?
При арифметическом сдвиге сдвиг вправо соответствует делению на 2 (в общем случае — на основание системы счисления).
10. В каком порядке следует выполнять действия для получения прямого кода двоичного целого числа из дополнительного кода? (НЕ УВЕРЕН)
Прямой обратный и дополнительный код - это модели представления целых чисел , как положительных, так и отрицательных. Во всех трех кодах старший разряд указывает на знак числа и он равен единице, если число отрицательное и нулю в противном случае. Остальные разряды содержат представление модуля числа. Различие между кодами наблюдается именно в способах представления модуля. Для положительного числа модуль во всех трех кодах представляется одинаково - это просто естественная запись двоичного числа. Для отрицательных чисел, в обратном коде это просто поразрядная инверсия прямого кода, а в дополнительном - к обратному коду, как к числу, просто прибавляется единица.
Вычесть единицу и инвертировать, кроме бита знака.
Как изменяется двоичное число при сдвиге влево
Эти четыре команды выполняют двоичный сдвиг приемника (регистр или переменная) вправо (в сторону старшего бита) или влево (в сторону младшего бита) на значение счетчика (число или регистр CL, из которого учитываются только младшие пять бит, которые могут принимать значения от 0 до 31), Операция сдвига на 1 эквивалентна умножению (сдвиг влево) или делению (сдвиг вправо) на 2. Так, число 0010b (2) после сдвига на 1 влево превращается в 0100b (4). Команды SAL и SHL выполняют одну и ту же операцию (на самом деле это одна и та же команда) — на каждый шаг сдвига старший бит заносится в CF, все биты сдвигаются влево на одну позицию, и младший бит обнуляется. Команда SHR выполняет прямо противоположную операцию: младший бит заносится в CF, все биты сдвигаются на 1 вправо, старший бит обнуляется. Эта команда эквивалентна беззнаковому целочисленному делению на 2. Команда SAR действует по аналогии с SHR, только старший бит не обнуляется, а сохраняет предыдущее значение, так что, например, число 11111100b (-4) перейдет в 11111110b (-2). SAR, таким образом, эквивалентна знаковому делению на 2, но, в отличие от IDIV, округление происходит не в сторону нуля, а в сторону отрицательной бесконечности. Так, если разделить -9 на 4 с помощью IDIV, результат будет -2 (и остаток -1), а если выполнить арифметический сдвиг вправо числа -9 на 2, результат будет -3. Сдвиги больше чем на 1 эквивалентны соответствующим сдвигам на 1, выполненным последовательно. Схема всех сдвиговых операций приведена на рис. 7.
Рис. 7. Сдвиговые операции
Сдвиги на 1 изменяют значение флага OF: SAL/SHL устанавливают его в 1, если после сдвига старший бит изменился (то есть старшие два бита исходного числа не были одинаковыми), и в 0, если старший бит остался тем же. SAR устанавливает OF в 0, и SHR устанавливает OF в значение старшего бита исходного числа. Для сдвигов на несколько бит значение OF не определено. Флаги SF, ZF, PF устанавливаются всеми сдвигами в соответствии с результатом, значение AF не определено (кроме случая, если счетчик сдвига равен нулю, в котором ничего не происходит и флаги не изменяются).
В процессорах 8086 непосредственно можно было задавать в качестве второго операнда только число 1 и при использовании CL учитывать все биты, а не только младшие 5, но уже начиная с 80186 эти команды приняли свой окончательный вид.
Приемник (регистр или переменная) сдвигается влево (в случае SHLD) или вправо (в случае SHRD) на число бит, указанное в счетчике (число или регистр CL, откуда используются только младшие 5 бит, которые могут принимать значения от 0 до 31). Старший (для SHLD) или младший (в случае SHRD) бит не обнуляется, а считывается из источника (регистр), значение которого не изменяется. Например, если приемник содержал 00101001b, источник 1010b, счетчик равен 3, SHRD даст в результате 01000101b, a SHLD — 01001101b (см. рис. 8).
Рис. 8. Сдвиги двойной точности
Флаг OF устанавливается при сдвигах на 1 бит, если изменился знак приемника, и сбрасывается, если знак не изменился; при сдвигах на несколько бит флаг OF не определен. Во всех случаях SF, ZF и PF устанавливаются в соответствии с результатом и AF не определен, кроме случая со сдвигом на 0 бит, в котором значения флагов не изменяются. Если счетчик больше, чем разрядность приемника, — результат и все флаги не определены.
Эти команды осуществляют циклический сдвиг приемника (регистр или переменная) на число бит, указанное в счетчике (число или регистр CL, из которого учитываются только младшие пять бит, принимающие значения от 0 до 31). При выполнении циклического сдвига на 1 команды ROR (ROL) сдвигают каждый бит приемника вправо (влево) на одну позицию, за исключением самого младшего (старшего), который записывается в позицию самого старшего (младшего) бита. Команды RCR и RCL выполняют аналогичное действие, но включают флаг CF в цикл, как если бы он был дополнительным битом в приемнике (рис. 9).
Рис. 9. Циклические сдвиги
После выполнения команд циклического сдвига флаг CF всегда равен последнему вышедшему за пределы приемника биту, флаг OF определен только для сдвигов на 1 — он устанавливается, если изменилось значение самого старшего бита, и сбрасывается, если старший бит не изменился. Флаги SF, ZF, AF и PF не изменяются.
Арифметические операции с фиксированной точкой
Операции сдвигов появились вместе с компьютерами. Они легко реализовываются на цифровых схемах и существуют практически на всех типах процессоров. В математике они заменяются операциями умножения и деления. Операции сдвигов удобно рассматривать на битовом представлении числа. При сдвиге все биты числа сдвигаются либо влево, либо вправо. Сдвиг на один бит влево равнозначен умножению на 2, сдвиг на один бит вправо равнозначен делению на 2. Есть отличия при операциях с беззнаковыми целыми числами и с целыми числами со знаком.
Логический (или беззнаковый) сдвиг влево
Логический сдвиг влево применяется при операциях над беззнаковыми целыми числами. При сдвиге влево все биты сдвигаются влево на один бит, старший бит отбрасывается, а в младший бит записывается 0. Если до операции в старшем бите была единица, то число после операции становится меньше исходного. В случае отбрасывания старшей единицы устанавливается флаг Carry.
Логический (беззнаковый) сдвиг вправо
Логический сдвиг вправо применяется при операциях над беззнаковыми целыми числами. При сдвиге вправо все биты сдвигаются вправо, отбрасывается младший бит, а в старший записывается 0. Если в младшем бите до операции была 1, то устанавливается флаг Carry.
Арифметический (для чисел со знаком) сдвиг вправо
Арифметический сдвиг вправо применяется при операциях со знаковыми целыми числами. При сдвиге вправо все биты сдвигаются вправо, отбрасывается младший бит, а старший бит дублируется, тем самым сохраняя знак. Арифметический сдвиг вправо равнозначен выполнению операции деления на 2.
Арифметический (для чисел со знаком) сдвиг влево
Арифметический сдвиг влево применяется при операциях со знаковыми целыми числами. При сдвиге влево все биты сдвигаются влево на один бит, старший бит отбрасывается, а в младший бит записывается 0. Если при сдвиге влево изменяется знаковый бит (с 1 на 0 или с 0 на 1), то происходит ситуация насыщение — устанавливается флаг Overflow и значение результата заменяется на максимальное целое число в случае, если до начала операции число было положительное или на минимальное целое, если до начала операции число было отрицательным. Арифметический сдвиг влево равнозначен выполнению операции умножения на 2.
Примеры
Рассмотрим использование арифметических и логических сдвигов. Для рассмотрения примеров выберем формат представления fractional данных.
| Общее количество бит (b) | 8 16 24 | ||
| Количество бит для целой части (m) | |||
| Количество бит для дробной части (n) | |||
Введем произвольное значение вещественного числа в формате float-point. После введения, число автоматически конвертируется в формат fractional и его бинарное представления. Если исходное вещественное число выходит за пределы допустимого представления в формате fractional, то оно будет автоматически приведено к допустимым пределам. Например, попробуйте ввести 1 при выбранном формате Q1.15.
| Арифметический сдвиг | ||
| Логический сдвиг | ||
| Float-Point | ||
| Fractional16 | ||
| Fractional2 | ||
| Флаги | ||
|---|---|---|
| Overflow | Carry | |
Побитовые операторы
Побитовые операторы интерпретируют операнды как последовательность из 32 битов (нулей и единиц). Они производят операции, используя двоичное представление числа, и возвращают новую последовательность из 32 бит (число) в качестве результата.
Эта глава требует дополнительных знаний в программировании и не очень важная, при первом чтении вы можете пропустить её и вернуться потом, когда захотите понять, как побитовые операторы работают.
Формат 32-битного целого числа со знаком
Побитовые операторы в JavaScript работают с 32-битными целыми числами в их двоичном представлении.
Это представление называется «32-битное целое со знаком, старшим битом слева и дополнением до двойки».
Разберём, как устроены числа внутри подробнее, это необходимо знать для битовых операций с ними.
- Что такое двоичная система счисления, вам, надеюсь, уже известно. При разборе побитовых операций мы будем обсуждать именно двоичное представление чисел, из 32 бит.
- Старший бит слева – это научное название для самого обычного порядка записи цифр (от большего разряда к меньшему). При этом, если больший разряд отсутствует, то соответствующий бит равен нулю. Примеры представления чисел в двоичной системе:
a = 0; // 00000000000000000000000000000000 a = 1; // 00000000000000000000000000000001 a = 2; // 00000000000000000000000000000010 a = 3; // 00000000000000000000000000000011 a = 255;// 00000000000000000000000011111111
00000000000000000000000100111010