## Логические команды 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 ```