Остальные логические команды на Фиг. 4.19 выполняют сдвиги данных. Команда сдвига перемещает все биты в поле данных либо вправо, либо влево. Это можно проиллюстрировать церковной скамьей, на которой сидят мужчины и женщины. Каждый раз, когда приходит новый человек и садится на край скамьи, остальные сидящие на ней сдвигаются на одно место. Если скамья уже заполнена, то крайний в результате такого сдвига вытесняется с нее. Команда сдвига делает в точности то же самое, только вместо женщин и мужчин здесь выступают нули и единицы.
ЪДДДДДДДДДДДДДї ЪДДДДДДДДДДДДДДДї
ЪДДДДї і ЪДДДДДДДДДї і і ЪДДДДДДДДДДї і ЪДДДДї
і CY Г<ДБДґ ДАННЫЕ Г<Щ АД>ґ ДАННЫЕ ГДБД>ґ CY і
АДДДДЩ АДДДДДДДДДЩ АДДДДДДДДДДЩ АДДДДЩ
ROL ROR
ЪДДДДДДДДДДДДДДДДДДДДДДДДДДї ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДї
і ЪДДДДї ЪДДДДДДДДДї і і ЪДДДДДДДДДДї ЪДДДДї і
АДДґ CY Г<ДДДґ ДАННЫЕ Г<ДДЩ АДДД>ґ ДАННЫЕ ГДДД>ґ CY ГДЩ
АДДДДЩ АДДДДДДДДДЩ АДДДДДДДДДДЩ АДДДДЩ
RCL RCR
ЪДДДДї ЪДДДДДДДДДї ЪДДДДДДДДДДї ЪДДДДї
і CY Г<ДДДґ ДАННЫЕ Г<ДДД 0 0 ДДД>ґ ДАННЫЕ ГДДД>ґ CY і
АДДДДЩ АДДДДДДДДДЩ АДДДДДДДДДДЩ АДДДДЩ
SHL SHR
ЪДДДДДДДї
і і
ЪДДДДї ЪДДДДДДДДДї і ЪДДДБДДДДДДї ЪДДДДї
і CY Г<ДДДґ ДАННЫЕ Г<ДДД 0 АДД>ґ ДАННЫЕ ГДДД>ґ CY і
АДДДДЩ АДДДДДДДДДЩ АДДДДДДДДДДЩ АДДДДЩ
SAL SAR
Фиг. 4.20 Операции сдвига.
В связи с арифметической природой, все команды сдвигов влияют на флаг переполнения так же, как и на флаг переноса. Флаг переполнения не определен в случае счетчиков сдвига больших единицы, но при единичных сдвигах команды устанавливают флаг переполнения только в случае, если в результате операции изменился знак числа. Если старший бит не изменился, флаг переполнения сбрасывается, т.е. флаг переполнения показывает, дает ли подразумеваемое сдвигом умножение или деление правильный результат в дополнительном коде.
На Фиг. 4.21 приведены два примера команд сдвига. Первый пример демонстрирует умножение на число с помощью команд сдвига влево. В примере выполняется умножение на 9, не являющееся степенью 2. Сначала в примере данные сдвигаются влево на три позиции, чтобы умножить число на 8. Затем программа складывает полученное значение с первоначальным, давая результат, равный первоначальному числу, умноженному на 9.
Недостатки этого метода очевидны. Он требует много больше команд, чем простое умножение - которое выглядело бы примерно так:
PUSH DX
MOVDX,9
IMUL DX
POPDX
Кроме того, умножение на 9 с помощью сдвига дает 16-битовый результат, а не 32-битовый, как команда IMUL.
Все же в программе умножение с помощью сдвига может оказаться желательным в некоторых случаях. В первую очередь, его преимущество - скорость выполнения. Команда IMUL требует много времени, тогда как команда сдвига выполняется гораздо быстрее. В случае примера на Фиг. 4.21, метод сдвига работает примерно на 25% быстрее. Выигрыш небольшой, но может оказаться решающим для приложения, зависящего от умножения целых чисел на 9. Умножения на степень 2 могут дать и больший выигрыш в скорости выполнения.
Microsoft (R) Macro Assembler Version 5.00 1/1/80 04:01:21
Фиг. 4.21 Примеры инструкций сдвига Page 1-1
PAGE ,132
TITLE Фиг. 4.21 Примеры инструкций сдвига
0000 CODE SEGMENT
ASSUME CS:CODE,DS:CODE
;--------------------------------------------------
; Эта программа умножает число, заданное в регистре AX
; на 9 без использования команды умножения
;--------------------------------------------------
0000 MUL9 PROC NEAR
0000 51 PUSH CX ; Сохранение регистра CX в стеке
0001 50 PUSH AX ; Временное сохранение AX
0002 B1 03 MOV CL, 3 ; Будем сдвигать регистр AX на 3 разряда,
0004 D3 F8 SAR AX, CL ; тем самым уножая на 8
0006 8B C8 MOV CX, AX ; CX <- AX * 8
0008 58 POP AX ; Восстановление AX
0009 03 C1 ADD AX, CX ; AX <- исходное значение * 9
000B 59 POP CX ;
000C C3 RET
000D MUL9 ENDP
;--------------------------------------------------
; Эта программа программа выделяет один бит в
; регистре AX, номер которого задан в регистре CL
;--------------------------------------------------
000D 53 PUSH BX ; Сохранение регистра BX в стеке
000E BB 0001 MOV BX, 1 ; Создание маски (1 в разряде 0 регистра BX)
0011 D3 C3 ROL BX, CL ; Сдвиг маски
0013 23 C3 AND AX, BX ; Выделение требуемого разряда
0015 5B POP BX ; Восстановление регистра BX
0016 C3 RET
0017 CODE ENDS
END
Фиг. 4.21 Примеры сдвига
Второй пример на Фиг. 4.21 показывает, как использовать сдвиг на переменное число разрядов для выборки отдельного бита. Этот фрагмент предполагает, что исходная информация находится в регистре AX, а регистр CL содержит номер бита, выбираемого из регистра AX: если содержимое регистра CL равно 8, из регистра AX выбирается бит 8. Программа сдвигает маску в регистре BX на указанную в регистре CL позицию, а команда AND изолирует выбранный бит.
Для того чтобы этот пример работал правильно, число в регистре CL должно быть в диапазоне 0 - 15. Можно было бы использовать команду AND, чтобы выделить младшие четыре бита значения сдвига в регистре CL; команда AND CL, 0FH гарантирует, что число в регистре CL находится в пределах 0 - 15. Вы можете изменить этот пример так, чтобы выделить более одного бита из слова. Можно было бы выделить тетраду из 16-битового слова, заменив значение маски в регистре BX.