## Логические команды
  
1. `NOT op`
```asm
MOV AL, 1100b ; AL = 00001100b
NOT AL ; AL = 11110011b
```
2. `AND op1, op2`

| op1 | op2           |
| --- | ------------- |
| r8  | i8, r8, m8    |
| m8  | i8, r8        |
| r16 | i16, r16, m16 |
| m16 | i16, r16      |
  
3. `OR op1, op2`  
4. `XOR op1, op2`  
  
Обнуление регистров: 
```asm
XOR AX, AX ; AX := 0
```
## Команды сдвига
Имеют два операнда. Первый операнд рассматривается как набор битов, которые будут сдвигаться влево или вправо на несколько позиций. Второй операнд рассматривается как целое без знака и определяет, на сколько позиций необходимо сдвинуть первый операнд. Второй операнд всегда находится в байтовом регистре CL и его значение не меняется командой сдвига. Команды сдвига меняют все флаги. Команды сдвига делятся на логический, арифметический и циклический.
1. **Логические сдвиги**: `SHL op, CL`, `SHR op, CL`
  
Бит, уходящий за пределы ячейки, заносится в флаг CF, а с другого конца в операнд добавляются нули.
```asm
MOV AL, 01000111b
SHR AL, 1 ; AL = 00100011b, CF = 1
MOV DH, 00111000b
MOV CL, 3
SHL DH, CL ; CF = 1, DH = 11000000b
```
![Логические сдвиги](../Pictures/05_01.%20Логические%20сдвиги.png)  
Основное применение команд логического сдвига - это быстрое умножение и деление целых чисел на степень двойки ($2^k$). При сдвиге числа 5 на 3 разряда влево получаем: `5 = 101b, 101000b = 40` = $5*2^3$. В общем случаи умножение на $2^k$ реализуется:
```asm
; op = op * 2^k
MOV CL, k
SHL op, CL
```
**Пример:**
```asm
; 37 * 16
MOV CL, 4
MOV AX, 37
SHL AX, CL
```
Правильно умножаются только знаковые числа от -64 до 63, или беззнаковые числа меньше 128, так как результат должен умещаться в ячейку.
При сдвиге на $k$ разрядов вправо происходит отбрасывание последних $k$ разрядов, что соответствует получению неполного частного от деления на $2^k$. Такое деление возможно только для беззнаковых чисел. Пример: `18 = 10010b 10b = 2 = 18 div` $2^3$
```asm
; op := op div 2^k
MOV CL, K
SHR op, CL ; Только для беззнаковых чисел
```
2. **Арифметические сдвиги**: `SAL op1, op2`, `SAR op1, op2`
  
После занесения уходящего бита в флаг CF, знаковый бит операнда восстанавливает свое значение. 
```asm
MOV BH, 10001110b
SAR BH, 1 ; BH = 11000111b, CF = 0
MOV BH, 0001110b
SAR BH, 1 ; BH = 00000111b, CF = 0
```
![Логические сдвиги](../Pictures/05_02.%20Логические%20сдвиги.png)  
3. **Циклические сдвиги**: `ROL op1, op2`, `ROR op1, op2`
  
Уходящий бит не теряется, а возвращается в операнд с другого конца и одновременно записывается в флаг CF.
```asm
MOV CH, 11000011b
ROL CH, 1 ; CF = 1, CH = 1000111b
MOV BH, 11100010b
ROL BH, 1 ; CF = 0, CH = 01110001b
```
Циклические сдвиги используются для перестановки частей содержимого ячейки или регистра.  
**Пример:** поменять местами правую и левую половины регистра AL
```asm
MOV AL, 17h ; AL = 00010111b
MOV CL, 4
ROL AL, CL ; AL = 01110001b = 71h
```
4. **Циклические сдвиги через перенос**: `RCL op, 1`, `RCR op, 1`
  
По команде `RCL` все биты левого операнда сдвигаются на одну позицию влево, причем самый первый записывается в флаг CF, а прежнее значение флага заносится в самый правый разряд операнда. Эти команды используются при переносе переменных/битов из одного регистра в другой.
```asm
MOV BL, 11110000b ; CF = 0
RCL BL, 1 ; CF = 1, BL = 11100000b
RCL BL, 1 ; CF = 1, BL = 1100001b
```
**Пример:** сдвинуть на 3 разряда влево значения регистров AL и DH, написав справа к AL 3 левых бита регистра DH
```asm
MOV CX, 3 ; сдвинуть на 3 влево
L: SHL DH, 1 ; значения регистров AL и DH
RCL AL, 1 ; справа к AL
LOOP L ; 3 левых бита регистра DH
```