CBW преобразует байт в регистре AL в слово в регистре АХ путем расширения знакового бита AL во все биты регистра AH. Команда CWD преобразует слово в регистре АХ в двойное слово , расположенное в паре регистров DX, AX путем расширения знакового бита регистра AX во все биты регистра DX.
Новые команды расширения знака
Начиная с микропроцессора 80386, существуют еще две команды расширения знака CWDE и CDQ. CWDE преобразует слово в расширенное двойное слово путем расширения знакового разряда АХ во все старшие разряды регистра ЕАХ. CDQ преобразует двойное слово в регистре ЕАХ в учетверенное слово в паре регистров EDX, EAX путем расширения знакового разряда ЕАХ во все разряды EDX.
2.5.2.5.Десятичная арифметика.
До сих пор мы рассматривали арифметические операции под двоичными числами, так как компьютеры работают только с двоичными числами, но для людей более привычны десятичные числа. Поэтому возникает проблема преобразования десятичных чисел в двоичные. Можно десятичное число представить в двоичной системе полностью, кодом, например 37 - 00100101, а можно закодировать отдельно каждую цифру 3 и 7 и получить код 0011 0111. Такое двоичное изображение десятичных чисел называется двоично-десятичным кодированием (BCD - кодом). Для выполнения арифметических операций над числами в данном формате потребовалось бы ввести соответствующие команды сложения, вычитания, умножения и деления. Возможен и второй вариант: применить к таким числам команды двоичной арифметики, заранее зная о неправильном результате, а затем выполнить команду коррекции, которая сформирует правильный результат в BCD формате. Именно такой вариант был выбран в процессорах семейства 8086.
Рассмотрим сложение чисел 23 и 14 в BCD формате с помощью двоичного сложения:
=
=
=
Результат правильный, коррекция не нужна
Сложим 29 и 14:
=
=
=
3?
Ответ неверен, так как код 1101 не соответствует десятичной цифре, требуется коррекция.
Коррекция заключается в том, чтобы добавить 6 к сумме в тех разрядах, где получена запрещённая комбинация, компенсируя этим, 6 запрещённых комбинаций для десятичных чисел (4 разряда - 16 комбинаций, 10 цифр правильных, 6 - лишних).
=
3?
=
=
Результат правильный
Более сложная ситуация возникает, когда сумма “проскакивает” запрещённый диапазон и становится допустимой цифрой.
Сложим 29 и 18:
=
=
=
Результат неверный, так как младшая цифра проскочила запрещенный диапазон.
При коррекции требуется добавить 6 и получить правильный результат 47. Однако необходимость такой коррекции невозможно определить по самому результату. Признаком “проскока” цифрой запрещённого диапазона служит перенос из соответствующего бита (разряда). В приведённом примере им будет перенос из младшего (десятичного) разряда в старший. Флаг CF показывает, что при сложении возник перенос из старшего бита (разряда), флаг вспомогательного переноса AF предназначен только для регистрации переноса из младшего 10-го разряда, зная который можно осуществить коррекцию. После сложения в нашем примере CF = 0 и AF = 1 (если CF = 1, то при следующем сложении надо учитывать его и сумму).
Десятичную коррекцию сложения осуществляет команда DAA, в которой предполагается, что сумма находится в регистре AL. С учётом содержимого AL и состояний флагов AF и CF команда DAA определяет необходимость коррекции и реализует её для AL.
Аналогично команда DAS корректирует результат после операции вычитания.
Для умножения чисел в формате BCD произвести коррекцию невозможно, так как в результате “замешаны” перекрёстные члены произведения. Аналогично и для команды деления. Следовательно, для умножения и деления необходимо перейти к другому представлению десятичных чисел. BCD формат называется упакованным, а в неупакованном формате байт содержит всего одну десятичную цифру. Она находится в 4-х младших битах, а старшие биты не влияют на значение цифры. Примером такого формата служит код ASCII, в котором символы представлены 8 битами. ASCII-коды десятичных цифр представлены в таблице 2.9.
Таблица 2.9. ASCII-коды десятичных цифр.
Цифра
Код
Четыре бита 0011 не влияют на значение цифры, однако, должны быть обнулены до выполнения арифметических операций.
Результаты двоичного сложения и вычитания ASCII-чисел можно скорректировать аналогично коррекции в BCD формате, причём корректируется только младшая цифра. В системе команд микропроцессора существуют специальные команды коррекции:
AAA - ASCII коррекция сложения.
AAS - ASCII коррекция вычитания.
AAM - ASCII коррекция умножения.
AAD - ASCII коррекция деления.
Пример: умножим 9 * 4, 9 - находится в регистре BL, а 4 - в регистре AL.
BL: 00001001 = 9 ½ MUL BL - даёт в AX 16-битный результат, равный 36
AL: 00000100 = 4 ½36 = 0000 0000 0010 0100
Команда коррекции AAM должна “разложить” результат на 3 (00000011) в регистре AH и 6 в регистре AL. Для этого нужно просто раз делить содержимое AL на 10 и поместить частное в AH, а остаток в AL.
Поэтому команда AAM имеет длину 2 байта, так как второй байт - это представление 10. В рассмотренном примере старшие биты были нулевыми, иначе результат нельзя скорректировать. Поэтому перед умножением неупакованных десятичных чисел следует сбросить четыре старших бита в 0.
Рассмотрим деление неупакованных десятичных чисел, например 42/6. 42 находится в AL (0000 0100 в AH и 0000010 в AL), а 6 (00000110) в BL. Неупакованное представление одноразрядного числа 6 является его двоичным представлением, следовательно, нужно преобразовать 42 в двоичное число. Для этого AH следует умножить на 10 и сложить с содержимым регистра AL. Тогда при делении в AL получится число 7, двоичное представление которого совпадает с неупакованным представлением. Команда коррекции деления имеет свои особенности:
AAD - двухбайтовая команда (второй байт - 10).
Коррекция AAD предшествует делению, а в сложении, вычитании и умножении производится после операции.
Делимое и делитель (множимое и множитель) должны иметь 0 в старших 4-х битах.
2.5.3.Логические команды.
Перечень логических команд и их описание приведено в таблице 2.10.
Таблица 2.10. Перечень логических команд.
Мнемоника
Описание
Булевы команды
AND (и)
приемник и источник à приемник
TEST
приемник и источник à
OR (или)
приемник или источник à приемник
XOR (исключающее или)
приемник Å источник à приемник
NOT (инверсия)
не приемник à приемник
Команды
SHL (логический сдвиг влево)
CF ß приемник ß 0
сдвигов
SHR (логический сдвиг вправо)
0 à приемник à CF
SAL (арифметический сдвиг влево)
CF ß приемник ß 0
SAR (арифметический сдвиг вправо)
знак à приемник à CF
Команды циклических
ROL (циклический сдвиг влево)
сдвигов
ROR (циклический сдвиг вправо)
RCL (циклический сдвиг влево через перенос)
RCR (циклический сдвиг вправо через перенос)
Начиная с м/п 80386 дополнительные команды:
Команды двойного сдвига
SHLD (сдвиг с двойной точностью влево)
SHRD (сдвиг с двойной точностью вправо)
Команды работы с двоичными цепочками
BT (поиск бита и запись его в CF)
BTC (поиск и инвертирование бита в цепочке)
BTS (поиск и установка бита в)
BTR (поиск и сброс бита )
BSF (сканирование цепочки битов вперед)
BSR (сканирование цепочки битов назад)
2.5.3.1.Булевы команды.
К булевым командам относятся команды AND, OR, XOR, NOT, TEST.
Команды AND, OR, XOR выполняют логическую функцию над соответствующими битами источника и приёмника, помещая результат в приёмник. Все команды двухоперандные , разрешённые форматы операндов такие же, как у команд ADD, ADC, SUB, SBB.
Команда NOT - однооперандная, она выполняет инверсию каждого бита операнда и помещает результат в то же место. Формат команды такой же, как у команд DEC, NEG, INC.
Команда AND удобна для обнуления указанных разрядов числа: один операнд определяет разряды, а второй число. Например: обнуление старших 4-х битов в байте с именем MEMB (AND MEMB, 00001111B).
Команда OR используется для установки указанных битов, а команда XOR используется для инвертирования указанных разрядов в числе. XOR позволяет также сбросить содержимое регистра в нуль (регистр должен быть и источником и приёмником).
Команда TEST - двухоперандная, формат совпадает с командами ADD, ADC, SUB, SBB. Объединяет возможности команд AND и CMP, Как AND она выполняет объединение по “и” соответствующих бит операндов, как CMP она сохраняет только состояния флагов, а не результат. Удобна для проверки того, есть ли в указанных разрядах числа хотя бы одна 1. Один операнд определяет разряды, второй - число. Если результат неравен 0, то, по крайней мере, один разряд равен 1. Все логические команды кроме NOT изменяют флаги SF, ZF, PF. Флаг AF - не определён, а CF = 0 и OF = 0, DF, IF, TF - не изменяются.
2.5.3.2.Команды сдвигов.
Команды сдвигов являются эффективным средством увеличения или уменьшения числа в 2 раза (меньше памяти и быстрее, чем в командах умножения и деления). Для умножения числа на 2, надо сдвинуть все биты на 1 разряд влево, а в освобождённый правый бит поместить 0. Если выдвинутый слева бит передать во флаг CF, то можно зафиксировать выход за диапазон, проверив условие CF = 1. Аналогично уменьшение беззнакового числа вдвое осуществляется сдвигом всех бит на один разряд вправо, а в освобождающийся бит помещается 0. Вдвигаемый справа бит передаётся во флаг CF, если CF = 1, то число нечётное. С беззнаковыми числами работает команда SHL и SHR, а команды SAL и SAR предназначены для знаковых чисел. SAR сохраняет знаковый бит неизменным, команда SHR помещает в знаковый бит 0 (но заносит 1 во флаг OF, если знак имеется). Отметим, что сдвиг вправо нечётного числа всегда даёт результат, который меньше половины числа, например:
-5 (1111 1011) SAR -3 (1111 1101)
-3 < -2.5
При делении -5 на 2 командой DIV результат будет = -2. Различий между удвоением знакового и беззнакового чисел нет.
Рисунок 2.3.
Графическое представление работы команд сдвигов