SHL – SHift logical Left – логический сдвиг операнда влево.
SHL операнд, количество_сдвигов
Флаги: SF, ZF, PF, CF. Флаг AF не определен. Флаг OF изменяется, если сдвиг осуществляется только на 1 разряд, иначе не определен. OF=1, если значение флага CF после сдвига и значение старшего бита результата различны, если совпадают – 0 (т.е. XOR от CF и старшего разряда результата).
Действие:
Сдвиг влево всех битов операнда на указанное количество разрядов. При этом выдвигаемый слева бит становится значением флага CF. Если команда записана в формате:
SHL операнд, 1 - осуществляется сдвиг влево на 1 бит. В младший бит операнда загружается 0;
SHL операнд, CL - осуществляется сдвиг влево на число битов, указанное в регистре-счетчике CL. В процессе последовательных сдвигов старшие биты операнда, пройдя через флаг CF, теряются, а младшие заполняются 0.
Команда полностью эквивалента команде SAL, поэтому для нее действует та же таблица с кодами операций.
Например, 1) MOV AL, 0Ch
SHL AL, 1 ; AL=18h, CF=0
2) SHR операнд, значение — логический сдвиг вправо (рис.1.19)
SHR – SHift logical operand Right – логический сдвиг операнда вправо.
SHR операнд, количество_сдвигов
Флаги: SF, ZF, PF, CF. Флаг AF не определен. Флаг OF устанавливается равным старшему значащему биту первоначального операнда. Флаг CF содержит значение последнего вдвинутого в него бита.
Действие:
Сдвиг вправо всех битов операнда. Младший бит операнда поступает в флаг CF. Освобождающиеся старшие разряды заполняются нулями.
Коды команды см. таблицу команды SAL. Но расширение кода операции при работе с непосредственным операндом, размещающееся в поле Reg/Opc в байте адресации, равно 101.
Например, 1) MOV AL, 7h
SHR AL, 1 ; AL=3, CF=1
2) MOV DX, 9513h
MOV CL, 8
SHR DX, CL ; BX=0095h, CF=0
0
CF операнд
операнд CF
Рис. 1.19Логический сдвиг влево и вправо
Операнд определяет, что сдвигать (объект может быть 8,16 или 32-разрядный). Значение устанавливает, на сколько позиций сдвигать. Значение может быть записано непосредственно в команде, но тогда оно может быть только равно 1, либо значение может быть задано в регистре CL. Для МП i286 и выше непосредственно в командах сдвига может быть записана константа, большая 1.
При сдвиге выдвигаемые биты последовательно перемещаются во флаг CF. Если сдвиг более чем на 1 разряд, то в CF остается только последний выдвигаемый бит. При сдвиге влево выдвигаются старшие биты числа, при сдвиге вправо — младшие. На освободившееся место записываются нули.
Примеры
1)mov al,01010100b
shl al,1 ; результат — 10101000b, в CF выдвинулся 0
; и справа в результате добавился 0
2)mov cl,3
mov al,01010100b
shr al,cl ; результат -00001010b, в CF выдвинулась 1
; и слева добавилось три 0
3).386
shr al,3; в регистре al все биты сдвигаются на 3
; разряда
Команды сдвига позволяют производить быстрое умножение (сдвиг влево) или деление (сдвиг вправо) на числа, являющиеся степенями 2. В первом примере произошло умножение на 2, во втором примере — деление на 8.
Чтобы это «почувствовать», представим себе, что наш компьютер не «двоичный», а «десятичный» (рис.1.20). В этом случае при умножении на 10 мы добавляем справа 0, что эквивалентно сдвигу числа на 1 позицию влево (5*10=50):
Рис. 1.20 Умножение на 10 с помощью сдвига
При делении удаляется справа 0, то есть происходит сдвиг числа вправо (500/10=050).
Это верно, если интерпретировать операнды как числа без знака. Для того чтобы можно было корректно работать с командами сдвига для чисел со знаком используют команды арифметического сдвига.
3) SAL операнд, значение — арифметический сдвиг влево (аналогично SHL)
В командах сдвигов в качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение.