- •Практическая работа №1
- •Практическая работа №2
- •Арифметические операции над числами с фиксированной точкой
- •Арифметические операции над двоичными числами с плавающей точкой
- •Практическая работа №3
- •Практическая работа №4
- •Практическая работа №5
- •Проверка состава оборудования
- •Практическая работа №6
- •Практическая работа №7
- •Команды сложения и вычитания
- •Команды умножения и деления Команды умножения
- •Команды деления
- •Изменение размера числа
- •Логические команды
- •Практическая работа №8
- •Прямой переход
- •Косвенный переход
- •Команды сравнения и условного перехода
- •Команды управления циклом
- •Практическая работа №9
Команды умножения и деления Команды умножения
Если сложение и вычитание беззнаковых и знаковых чисел производятся по одним и тем же алгоритмам, то умножение чисел этих двух классов выполняется по разным алгоритмам, в связи с чем в ПК имеются две команды умножения:
Умножение целых без знака (multiply): MUL ор
Умножение целых со знаком (integer multiply): IMUL ор
В остальном эти команды действуют одинаково:
Умножение байтов: АХ:=АL*ор (ор: r8, m8)
Умножение слов: (DX,AX):=АХ*ор (ор: rl6, ml6)
Операнд ор, указываемый в команде, - это лишь один из сомножителей; он может находиться в регистре или в памяти, но не может быть непосредственным операндом. Местонахождение другого сомножителя фиксировано и потому в команде не указывается явно: при умножении байтов он берется из регистра AL, а при умножении слов - из регистра АХ.
Местонахождение результата умножения также заранее известно и потому в команде явно не указывается. При этом под результат отводится в два раза больше места, чем под сомножители. Это связано с тем, что умножение n-значных чисел в общем случае дает произведение из 2n цифр, и с желанием сохранить все цифры произведения. При умножении байтов результат имеет размер слова и записывается во весь регистр АХ (в АН - старшие цифры произведения, в AL - младшие), а при умножении слов результат имеет размер двойного слова и записывается в два регистра - в регистр DX заносятся старшие цифры произведения, а в регистр АХ - младшие цифры.
Примеры:
N DB 10
...
MOV AL, 2
MUL N ; AX=2*10=20=0014h: AH=00h, AL=14h
MOV AL, 26
MUL N ; AX=26*10=260=0104h: AH=01h, AL=04h
MOV AX, 8
MOV ВХ, -1
IMUL ВХ ; (DX,AX)= -8=0FFFFFFF8h: DX-0FFFFh, AX=0FFF8h
Итак, команды умножения выдают результат в удвоенном формате. Это не всегда удобно: то мы работали с числами-байтами, а тут приходится переходить на обработку чисел-слов. В то же время далеко не всегда величина произведения столь велика, что ему нужен удвоенный формат; например, в первой и третьей из наших команд умножения для результата вполне достаточно было бы обычного формата. Поэтому важно знать, действительно ли произведению нужен двойной формат или ему достаточно и одинарного формата. Иногда об этом известно заранее (мы заранее знаем, что перемножаются небольшие числа), но иногда это можно установить только после умножения. В последнем случае вопрос о том, умещается ли результат умножения в формат сомножителей или нет, решается с помощью анализа флагов переноса CF и переполнения OF, которые в обеих командах умножения меняются синхронно и по следующему правилу:
CF=OF=1 - если произведение занимает двойной формат
CF=OF=0 - если произведению достаточен формат сомножителей
При CF=0 (одновременно и OF=0) можно считать, что произведение байтов занимает только регистр AL, а произведение слов - только регистр АХ, и дальше можно работать только с этими регистрами. Но если CF=1, то далее приходится работать с произведением как с числом удвоенного формата.
Команды деления
Как и умножение, деление чисел без знака и со знаком также реализуется двумя командами:
Деление целых без знака (divide): DIV ор
Деление целых со знаком (integer divide): IDIV ор
Первая из этих команд предназначена для деления беззнаковых целых чисел, а вторая - для деления знаковых чисел, в остальном же эти команды действуют одинаково:
деление слова на байт:
АН:=АХ mod op, AL:=AX div op (op: r8, m8)
деление двойного слова на слово:
DX:=(DX,AX) mod op, AX:=(DX,AX) div op (op: rl6, ml6)
Как видно, в этих командах местонахождение первого операнда (делимого) и результата фиксировано и потому явно не указывается. Указывается только второй операнд (делитель), который может находиться в регистре или в ячейке памяти, но не может быть непосредственным операндом.
При делении слова на байт делимое обязано находиться в регистре АХ, а делитель должен быть байтом. При делении двойного слова на слово делимое обязано находиться в двух регистрах - в DX (старшая часть делимого) и в АХ (младшая часть), а делитель должен иметь размер слова.
В области целых чисел "настоящее" деление невозможно, и в ПК под делением понимают получение сразу двух величин - неполного частного (div) и остатка (mod). Оба этих числа помещаются на место делимого: его старшая часть заменяется на остаток, а младшая - на неполное частное. Оба этих числа имеют один и тот же размер, совпадающий с размером второго операнда (делителя).
Если через функцию trunc (x) обозначить отбрасывание дробной части вещественного числа х, тогда операции div и mod определяются следующим образом:
а div b - trunc (a/b)
a mod b = а-b*(а div b)
Примеры:
13 div 4 =trunc (3.25)= 3 13 mod 4 =13-4*3 = 1
(-13)div 4 =trunc(-3.25)= -3 (-13)mod 4 =(-13)-4*(-3) = -1
13 div(-4) =trunc(-3.25)= -3 13 mod(-4) =13-(-4)*(-3) = 1
(-13)div(-4) =trunc(3.25)= 3 (-13)mod (-4) =(-13)-(-4)*3 = -1
И, наконец, отметим, что при выполнении команды деления возможно появление ошибки с названием "деление на 0 или переполнение". Она возникает в двух случаях:
делитель равен 0 (op=0),
неполное частное не вмещается в отведенное ему место (регистр AL или АХ); это, например, произойдет при делении 600 на 2:
MOV AX, 600
MOV BH, 2
DIV ВН ; 600 div 2 = 300, но 300 не вмещается в AL
При такой ошибке ПК прекращает выполнение программы.