Команды сдвига

Команды сдвига также обеспечивают манипуляции над отдельными битами операндов. Эти команды перемещают биты в поле операнда влево или вправо в зависимости от кода операции. Формат всех команд сдвига одинаков и приведен на рис.8.2.

 

Рис. 8.2. Формат команд сдвига

 

Операнд располагается обычно в регистре общего назначения, хотя может находиться и в памяти. Счетчик сдвигов определяет, на сколько бит необходимо сдвинуть операнд. Он может задаваться как непосредственно, так и через регистр CL и принимать значение в диапазоне от 0 до 31.

Все команды сдвига устанавливают флаг переноса CF. По мере сдвига битов за пределы операнда они сначала попадают во флаг переноса, устанавливая его равным значению очередного бита, оказавшегося за пределами операнда. Куда этот бит попадет дальше, зависит от типа команды сдвига и алгоритма программы.

Выделяют два типа команд сдвига:

– команды линейного сдвига;

– команды циклического сдвига.

В командах линейного сдвига очередной выдвигаемый бит перемещается во флаг CF, а при следующем сдвиге его значение теряется.

Команды линейного сдвига делятся на два типа:

– команды логического (беззнакового) линейного сдвига;

– команды арифметического (знакового) линейного сдвига.

При выполнении команды логического сдвига влево SHL (от англ. SHhift logical Left – сдвинуть влево логически) содержимое операнда сдвигается влево на количество битов, определяемое значением счетчика сдвигов. Справа (в позицию младшего бита) вписываются нули.

При выполнении команды логического сдвига вправо SHR (от англ. Shift logical Right – сдвинуть вправо логически) содержимое операнда сдвигается вправо на количество битов, определяемое значением счетчика сдвигов. Слева (в позицию старшего (знакового) бита) вписываются нули.

При выполнении команды арифметического сдвига влево SAL (от англ. Shift Arithmetic Left – сдвинуть влево арифметически) содержимое операнда сдвигается влево на количество битов, определяемое значением счетчика сдвигов. Справа в операнд вписываются нули. Команды SAL и SHL полностью идентичны.

При выполнении команды логического сдвига вправо SAR (от англ. Shift Arithmetic Right – сдвинуть вправо арифметически) содержимое операнда сдвигается вправо на количество битов, определяемое значением счетчика сдвигов. Слева в операнд вписывается знак (бит определяющий знак) исходного операнда.

Формат команд, а также принцип их работы показаны на рис.8.3 – 8.6.

 

Рис. 8.3. Формат команды SHL и принцип ее работы

Рис. 8.4. Формат команды SHR и принцип ее работы

 

Рис. 8.5. Формат команды SAL и принцип ее работы

 

Рис. 8.6. Формат команды SAR и принцип ее работы

Следующий фрагмент иллюстрирует выполнение команды SHR:

 

MOV CL,04D ;Счетчик сдвигов

MOV AL,10010101B

SHR AX,1 ;01001010 ;Сдвиг вправо на 1 бит

SHR AX,CL ;00000100 ;Сдвиг вправо на 4 бита

 

Следующий фрагмент иллюстрирует выполнение команды SAR:

 

MOV CL,04D ;Счетчик сдвигов

MOV AL,10010101B

SAR AX,1 ;11001010 ;Сдвиг вправо на 1 бит

SAR AX,CL ;11111100 ;Сдвиг вправо на 4 бита

 

Команды логического сдвига влево можно использовать для умножения беззнаковых чисел на два, а логического сдвига вправо для деления беззнаковых чисел на два (а в общем случае умножения или деления на число ). Эти действия будут выполняться быстрее, чем обычные операции умножения и деления. Действительно, например,

10D = 00001010B,

20D = = 00010100B,

40D = = 00101000B,

80D = = 01010000B и т.д.

Деление таким же образом пополам нечетных беззнаковых чисел (например, пяти или семи) образует меньшие значения (два или три, соответственно) и устанавливает флаг CF в 1.

Для деления знаковых чисел можно использовать команду арифметического сдвига вправо, которая сохраняет знак числа.

Результат операции умножения или деления должен по размеру помещаться в ту ячейку или в тот регистр, которые используются для хранения числа.

В командах циклического сдвига очередной выдвигаемый бит не теряется, а помещается обратно в тот же операнд.

Команды циклического сдвига делятся на два типа:

– команды простого циклического сдвига;

– команды циклического сдвига через флаг переноса CF.

При выполнении команды циклического сдвига влево ROL (от англ. ROtate Left – вращать влево) содержимое операнда сдвигается влево на количество битов, определяемое значением счетчика сдвигов. Сдвигаемые влево биты записываются в тот же операнд справа.

При выполнении команды циклического сдвига вправо ROR (от англ. ROtate Right – вращать вправо) содержимое операнда сдвигается вправо на количество битов, определяемое значением счетчика сдвигов. Сдвигаемые вправо биты записываются в тот же операнд слева.

При выполнении этих команд циклически сдвигаемый бит не только записывается в операнд с другого конца, но и одновременно его значение копируется во флаг CF.

Команды циклического сдвига через флаг переноса CF отличаются от команд простого циклического сдвига тем, что сдвигаемый бит не сразу попадает в операнд с другого его конца, а записывается сначала во флаг переноса CF. Лишь следующее исполнение данной команды сдвига (при условии, что она выполняется в цикле) приводит к помещению выдвинутого ранее бита с другого конца операнда.

При выполнении команды циклического сдвига влево через перенос RCL (от англ. Rotate through Carry Left – вращать влево через перенос) содержимое операнда сдвигается влево на количество битов, определяемое значением счетчика сдвигов. Сдвигаемые биты поочередно становятся значением флага переноса CF.

При выполнении команды циклического сдвига вправо через перенос RCR (от англ. Rotate through Carry Right – вращать вправо через перенос) содержимое операнда сдвигается вправо на количество битов, определяемое значением счетчика сдвигов. Сдвигаемые биты поочередно становятся значением флага переноса CF.

Формат команд, а также принцип их работы показаны на рис.8.7 – 8.10.

 

Рис. 8.7. Формат команды ROL и принцип ее работы

 

 

Рис. 8.8. Формат команды ROR и принцип ее работы

 

Рис. 8.9. Формат команды RCL и принцип ее работы

 

Рис. 8.10. Формат команды RCR и принцип ее работы

Далее последовательность команд иллюстрирует операцию циклического сдвига ROR:

 

MOV CL,5 ;Счетчик сдвигов

MOV BL,10000101B

ROR BL,CL; 00101100 ;Циклический сдвиг вправо на пять бит

 

Для того, чтобы обменять содержимое двух половинок регистра AX, достаточно выполнить следующую последовательность команд:

 

MOV AX,FBAEH

MOV CL,8 ;Счетчик сдвигов

ROL AX,CL

 

Вопросы для самопроверки

1. Написать фрагмент программы для сброса седьмого бита числа, находящегося в регистре CX.

2. Определите значение, находящееся в регистре BL, после выполнения следующей последовательности команд:

MOV BL,4EH

AND BL,2AH

3. Определите значение, находящееся в регистре BL, после выполнения следующей последовательности команд:

MOV BL,7FH

OR BL,36H

4. Определите значение, находящееся в регистре BL, после выполнения следующей последовательности команд:

MOV BL,D3H

XOR BL,9FH

5. Написать фрагмент кода для выполнения умножения беззнакового числа находящегося в регистре AX на 9, используя команды сдвига.

6. Написать фрагмент кода для выполнения умножения беззнакового числа находящегося в регистре AX на 12, используя команды сдвига.

7. Какое число будет находиться в регистре AL после выполнения следующих команд?

MOV AL,1EH

SHR AL,3

ROR AL,2

SAL AL,1