Учебный курс. Часть 18. Линейный сдвиг
Сдвиги — это особые операции процессора, которые позволяют реализовать различные преобразования данных, работать с отдельными битами, а также быстро выполнять умножение и деление чисел на степень 2. В этой части мы рассмотрим операции линейного сдвига, а в следующей будут циклические.
Логический сдвиг вправо
Логический сдвиг всегда выполняется без учёта знакового бита. Для логического сдвига вправо предназначена команда SHR. У этой команды два операнда. Первый операнд представляет собой сдвигаемое значение и на его место записывается результат операции. Второй операнд указывает, на сколько бит нужно осуществить сдвиг. Этим операндом может быть либо непосредственное значение, либо регистр CL. Схема выполнения операции показана на рисунке:
Все биты операнда сдвигаются вправо (от старших битов к младшим). Выдвинутый бит становится значением флага CF. Старший бит получает нулевое значение. Эта операция повторяется несколько раз, если второй операнд больше единицы. Логический сдвиг вправо можно использовать для деления целых чисел без знака на степень 2, причём сдвиг работает быстрее, чем команда деления DIV. Примеры:
shr ax,1 ;Логический сдвиг AX на 1 бит вправо shr byte[bx],cl ;Лог. сдвиг байта по адресу BX на СL бит вправо shr cl,4 ;CL = CL / 16 (для числа без знака) |
shr ax,1 ;Логический сдвиг AX на 1 бит вправо shr byte[bx],cl ;Лог. сдвиг байта по адресу BX на СL бит вправо shr cl,4 ;CL = CL / 16 (для числа без знака)
Арифметический сдвиг вправо
Арифметический сдвиг отличается от логического тем, что он не изменяет значение старшего бита, и предназначен для чисел со знаком. Арифметический сдвиг вправо выполняется командой SAR. У этой команды тоже 2 операнда, аналогично команде SHR. Схема выполнения операции показана на рисунке:
Выдвинутый бит становится значением флага CF. Знаковый бит не изменяется. При сдвиге на 1 бит сбрасывается флаг OF. Эту команду можно использовать для деления целых чисел со знаком на степень 2 (обратите внимание, что «округление» всегда в сторону меньшего числа, поэтому для отрицательных чисел результат будет отличаться от результата деления с помощью команды IDIV). Примеры:
sar bx,1 ;Арифметический сдвиг BX на 1 бит вправо sar di,cl ;Арифметический сдвиг DI на CL бит вправо sar [x],3 ;x = x / 8 (x - 8-битное значение со знаком) |
sar bx,1 ;Арифметический сдвиг BX на 1 бит вправо sar di,cl ;Арифметический сдвиг DI на CL бит вправо sar [x],3 ;x = x / 8 (x — 8-битное значение со знаком)
Логический и арифметический сдвиг влево
Логический сдвиг влево выполняется командой SHL, а арифметический — командой SAL. Однако, на самом деле это просто синонимы для одной и той же машинной команды. Сдвиг влево одинаков для чисел со знаком и чисел без знака. У команды 2 операнда, аналогично командам SHR и SAR.Схема этой операции показана на рисунке:
Старший бит становится значением флага CF, а младший получает нулевое значение. С помощью сдвига влево можно быстро умножать числа на степень 2. Но будьте внимательны, чтобы не получить в результате переполнение. Если при сдвиге на 1 бит меняется значение старшего бита, то устанавливается флаг OF. Примеры использования команды:
shl dx,1 ;Сдвиг DX на 1 бит влево sal dx,1 ;То же самое shl ax,cl ;Сдвиг AX на CL бит влево sal [x],2 ;x = x * 4 |
shl dx,1 ;Сдвиг DX на 1 бит влево sal dx,1 ;То же самое shl ax,cl ;Сдвиг AX на CL бит влево sal [x],2 ;x = x * 4
Сдвиги двойной точности
Существуют ещё две команды, осуществляющие более сложные сдвиги. SHRD — сдвиг двойной точности вправо, SHLD — сдвиг двойной точности влево. У этих команд 3 операнда. Первый операнд — сдвигаемое значение и место для записи результата, должен иметь размер 16 бит. Второй операнд — источник вдвигаемых битов, тоже должен иметь размер 16 бит и находится в одном из регистров. Значение второго операнда не меняется. Третий операнд — счётчик сдвигов, может быть непосредственным значением или находиться в регистре CL. Схемы работы этих команд показаны на рисунке:
Небольшой пример использования команды SHLD:
shld ax,bx,3 ;Сдвинуть ax на 3 бита влево, ;3 старших бита BX становятся младшими битами AX |
shld ax,bx,3 ;Сдвинуть ax на 3 бита влево, ;3 старших бита BX становятся младшими битами AX
Пример программы
Программа печатает переменную размером 16-бит в двоичном виде. Используется команда сдвига влево на 1 бит, после чего анализируется значение флага CF. Если CF=0, выводим символ ‘0’, если СF=1 выводим символ ‘1’. Проверка битов осуществляется в цикле.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h jmp start ;Безусловный переход на метку start ;-- Данные ------------------------------------------------------------ v dw 12345 pak db 13,10,'Press any key...$' ;---------------------------------------------------------------------- start: mov bx,[v] ;BX = v mov ah,2 ;Функция DOS 02h - вывод символа mov cx,16 ;Инициализация счётчика цикла lp: shl bx,1 ;Сдвиг BX на 1 бит влево mov dl,'0' ;dl = '0' jnc print ;Переход, если выдвинутый бит равен 0 inc dl ;dl = dl + 1 = '1' print: int 21h ;Обращение к функции DOS 02h loop lp ;Команда цикла mov ah,9 ;\ mov dx,pak ; > Вывод строки 'Press any key...' int 21h ;/ mov ah,8 ;\ int 21h ;/ Ввод символа без эха mov ax,4C00h ;\ int 21h ;/ Завершение программы |
use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h jmp start ;Безусловный переход на метку start ;— Данные ———————————————————— v dw 12345 pak db 13,10,’Press any key…$’ ;———————————————————————- start: mov bx,[v] ;BX = v mov ah,2 ;Функция DOS 02h — вывод символа mov cx,16 ;Инициализация счётчика цикла lp: shl bx,1 ;Сдвиг BX на 1 бит влево mov dl,’0′ ;dl = ‘0’ jnc print ;Переход, если выдвинутый бит равен 0 inc dl ;dl = dl + 1 = ‘1’ print: int 21h ;Обращение к функции DOS 02h loop lp ;Команда цикла mov ah,9 ;\ mov dx,pak ; > Вывод строки ‘Press any key…’ int 21h ;/ mov ah,8 ;\ int 21h ;/ Ввод символа без эха mov ax,4C00h ;\ int 21h ;/ Завершение программы
Результат работы программы:
Упражнение
Объявите массив из 8 слов без знака. Сдвиньте первый элемент на 1 бит влево, второй элемент — на 2 бита вправо (логическим сдвигом), третий элемент — на 3 бита влево и т.д. до конца массива. Используйте циклы. Проверьте работу программы в отладчике. Результаты можете выкладывать в комментариях.
Следующая часть »
asmworld.ru
4.1. Логические операции
Операция логического суммирования выполняется над двумя кодами и генерирует код той же разрядности, что и операнды, у которого в некотором i-м разряде находится единица, если хотя бы в одном операнде в i-м разряде имеет место единица.
Пример:
10001101 11110000 = 11111101.
Операция логического умножения выполняется над двумя кодами и генерирует код той же разрядности, что и операнды, у которого в некотором i-м разряде находится единица, если оба операнда в этом i-м разряде имеются единицу, и ноль во всех других случаях.
Пример:
10001101 11110000 = 10000000
Операция суммирования по модулю 2
Пример
10001101 11110000 = 01111101.
Операция логического отрицания выполняется над одним кодом и генерирует результирующий код той же разрядности, что и операнд, в некотором i-м разряде которого находится значение, противоположное значению в i-м разряде отрицаемого кода.
Операции сдвига в свою очередь, подразделяются на:
логические сдвиги, которые имеют разновидности – сдвиг вправо, сдвиг влево, циклический сдвиг вправо, циклический сдвиг влево;
арифметические сдвиги вправо и влево, выполнение которых зависит от знака и кода сдвигаемого числа.
4.2. Логические сдвиги
Сдвиг влево выполняется за счет установки в разряд значения, соответствующего исходному значению в ближайшем младшем разряде (освобождающийся самый правый т.е. самый младший, разряд заполняется 0, а «выталкиваемый» разряд пропадает). Например, код 11001110 после сдвига влево будет иметь вид 10011100.
Сдвиг вправо выполняется за счет установки в разряд значения, соответствующего исходному значению в ближайшем старшем разряде (в освобождающийся самый левый, т.е. самый старший, разряд заполняется 0, «выталкиваемый» разряд пропадает). Например, код 11001110 после сдвига влево будет иметь вид 01100111.
Циклический сдвиг влево выполняется за счет установки в разряд значения, соответствующего исходному значению в ближайшем младшем разряде (в освобождающийся самый правый, т.е. самый младший, разряд заносится значение старшего, т.е. самого левого разряда исходного кода). Например, код 11001110 после сдвига влево будет иметь вид 10011101.
Циклический сдвиг вправо выполняется за счет установки в разряд значения, соответствующего исходному значению в ближайшем старшем разряде (в освобождающийся самый левый т.е. самый старший, разряд заполняется значение в самом младшем разряде исходного кода). Например, код 11001110 после сдвига влево будет иметь вид 01100111.
4.3. Арифметические сдвиги
Арифметические сдвиги обеспечивают выполнение умножения (сдвиги влево) или операции деления (сдвиги вправо) двоичных кодов на два, точно так же, как сдвиги вправо и влево десятичного числа обеспечиваю выполнение деления и умножение на 10.
Арифметические сдвиги влево двоичного прямого кода выполняются в зависимости от того, какое сдвигается число – положительное или отрицательное.
Если сдвигается положительное число, то сдвиг (вправо или влево) выполняется как соответствующий логический сдвиг (влево или вправо), с той лишь разницей, что предусматриваются средства определения факта переполнения при сдвиге влево, что реализуется и при всех других арифметических операциях. При любом сдвиге вправо предусматриваются средства для округления после завершения нужного количества сдвигов и средства обнаружения обнуления сдвигаемой величины после очередного сдвига.
Арифметические сдвиги влево положительных двоичных чисел выполняются не зависимо от используемого кода (прямого обратного, дополнительного). Его реализация иллюстрируются следующими примерами.
Примеры
Найти результат арифметического сдвига влево на три разряда двоичного прямого кода числа [А]пк= 00.00000101
Решение
Процесс выполнения заданного сдвига дает следующие промежуточные и конечное значения:
первый сдвиг: 00.00000101 00.00001010;
второй сдвиг: 00.00001010 00.00010100;
третий сдвиг: 00.00010100 00.00101000.
Найти результат арифметического сдвига влево на четыре разряда двоичного прямого кода числа [А]пк= 00.00101.
Решение
Процесс заданного сдвига дает следующие промежуточные и конечное значения:
первый сдвиг: 00.00101 00.01010;
второй сдвиг: 00.01010 00.10100;
третий сдвиг: 00.10100 01.01000.
После третьего сдвига будет выработан сигнал переполнения, так как после очередного сдвига в разрядах знакового поля появятся разные значения. Таким образом, не считая процедуры определения переполнения, арифметический сдвиг влево выполняется точно так же, как и логический сдвиг влево.
3. Найти результат арифметического сдвига вправо на два разряда двоичного прямого кода числа [А]пк = 00.00000110.
Решение
Процесс заданного сдвига дает следующие промежуточные и конечное значение:
первый сдвиг: 00. 00000110 00. 00000011;
второй сдвиг: 00. 00000011 00. 00000001;
После выполнения заданного количества сдвигов выполняется округление на основании последнего «вытолкнутого» разряда; в данном случае последний «вытолкнутый» разряд равен 1, поэтому конечный результат выполнения заданного сдвига будет равен
studfile.net
Логический сдвиг — это… Что такое Логический сдвиг?
Би́товый сдвиг — изменение позиций битов в слове на одну и ту же величину.
В основной своей массе компьютеры не могут напрямую адресовать биты, которые содержатся группами по 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.
dic.academic.ru
Команды сдвига — Побитовая обработка
В программировании сдвигом называют одновременное перемещение границ расположения некоторой информации. Здесь можно провести хорошую аналогию с перемещениями, возникающими вследствие умножения или деления числа на какую-либо степень двойки. Пусть, например, некоторый байт содержит число 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)
показывают, на какое количество разрядов должен быть произведен сдвиг. Содержимое регистра может быть сдвинуто на указываемое таким образом количество разрядов вправо или влево.
SLL R1,D2(B2) |
Shift Left Logical |
Сдвиг R1 влево наD2-f(B2) разрядов |
SRL R1,D2(B2) |
Shift Right Logical |
Сдвиг (R1) вправо на D2+(B2) разрядов (учитываются последние6 разрядов) |
Команды логического сдвига обычно используются для придания двоичной информации более компактной формы. Например, чтобы запомнить последовательность, состоящую из 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 — СДВИГ ВПРАВО ДВОЙНОЙ КОДА).
SLDR R1,D2(B2) |
Shift Left Double Logical |
Сдвиг (R1.R1 + 1) влево на D2 + (B2) разрядов |
SRDL R1,D2(B2) |
Shift Right Double Logical |
Сдвиг (R1.R1+1) вправо на D2 + (B2) (учитываются последние6 разрядов) |
Здесь 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
itteach.ru
Битовый сдвиг — это… Что такое Битовый сдвиг?
Би́товый сдвиг — изменение позиций битов в слове на одну и ту же величину.
Большинство компьютеров не могут напрямую адресовать биты, которые содержатся группами по 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
значение вышедшего бита.
Ссылки
dic.academic.ru
Арифметический сдвиг Википедия
Би́товый сдвиг — изменение позиций бит в машинном слове.
Большинство компьютеров не могут напрямую адресовать биты, которые содержатся группами по 8, 16, 32 или 64 бита в машинном слове. Для обеспечения работы с битами существует множество машинных инструкций, включающие различные типы сдвигов. Все сдвиги похожи друг на друга поведением средних битов, которые просто сдвигаются влево или вправо на определённую величину. Однако, поведение крайних битов, которые уходят из слова и которые появляются в слове, зависит от типа сдвига.
В электронике битовые сдвиги выполняются на сдвиговых регистрах.
Логический сдвиг
Логический сдвиг влево | Логический сдвиг вправо |
Сдвиг, при котором уходящий бит исчезает, не влияя на оставшиеся биты, а на месте появившегося бита записывается бит 0.
Пример работы операции сдвига:
- Пусть у нас есть число 10101010b (в двоичной системе).
- Если сделать сдвиг влево на 1 бит, то получим число 01010100b.
- Если сделать сдвиг исходного числа вправо на 1 бит, то получим число 01010101b.
В большинстве процессоров уходящий бит сохраняется во флаге переноса. Эта функция широко используется при работе с многобайтовыми числами.
Арифметический сдвиг
Арифметический сдвиг влево | Арифметический сдвиг вправо |
При этом сдвиге слово рассматривается не просто как группа битов, а как целое число в дополнительном коде. При сдвиге влево ведёт себя как логический сдвиг, при сдвиге вправо уходящий бит исчезает, не влияя на оставшиеся биты, а на месте появившегося бита устанавливается бит, соответствующий знаку.
Пример № 1
Пример работы операции сдвига 8 битного числа в прямом коде:
- Пусть у нас есть 8 битное число: 00000010b = 2. (записанное в двоичной системе, в прямом коде).
- Cдвиг влево на 1 бит, даёт число: 00000100b = 4.
- Сдвиг вправо на 1 бит, даёт число: 00000001b = 1.
Пример № 2
Пример работы операции сдвига 8 битного числа записанного в дополнительном до 2х коде:
- Пусть у нас есть число 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, флаг переноса равен 1.
Операция циклического сдвига через бит переноса используется при работе с многобайтовыми числами. В частности, чтобы сдвинуть вправо на 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
значение вышедшего бита.
Ссылки
wikiredia.ru
Арифметический сдвиг Википедия
Би́товый сдвиг — изменение позиций бит в машинном слове.
Большинство компьютеров не могут напрямую адресовать биты, которые содержатся группами по 8, 16, 32 или 64 бита в машинном слове. Для обеспечения работы с битами существует множество машинных инструкций, включающие различные типы сдвигов. Все сдвиги похожи друг на друга поведением средних битов, которые просто сдвигаются влево или вправо на определённую величину. Однако, поведение крайних битов, которые уходят из слова и которые появляются в слове, зависит от типа сдвига.
В электронике битовые сдвиги выполняются на сдвиговых регистрах.
Логический сдвиг[ | ]
Логический сдвиг влево | Логический сдвиг вправо |
Сдвиг, при котором уходящий бит исчезает, не влияя на оставшиеся биты, а на месте появившегося бита записывается бит 0.
Пример работы операции сдвига:
- Пусть у нас есть число 10101010b (в двоичной системе).
- Если сделать сдвиг влево на 1 бит, то получим число 01010100b.
- Если сделать сдвиг исходного числа вправо на 1 бит, то получим число 01010101b.
В большинстве процессоров уходящий бит сохраняется во флаге переноса. Эта функция широко используется при работе с многобайтовыми числами.
Арифметический сдвиг[ | ]
Арифметический сдвиг влево |
ru-wiki.ru