Арифметические команды
Изучение команд для выполнения арифметических операций начнём с команд сложения и вычитания целых чисел. Определим вид и допустимые операнды у команд сложения и вычитания:
КОП op1, op2, где КОП = add, sub, adc, sbb.
add – сложение,
sub – вычитание:
op1 := op1 ± op2
adc – сложение с учётом флага переноса,
sbb – вычитание с учётом флага переноса:
op1 := op1 ± op2 ± CF
Таблица допустимых операндов для этих команд:
op1 | op2 |
R8 | r8, m8, i8 |
M8 | r8, i8 |
R16 | r16, m16, i16 |
M16 | r16, i16 |
В результате выполнения операций изменяются флаги CF, OF, ZF, SF, которые отмечают соответственно за перенос, переполнение, нулевой результат и знак результата (флагу SF всегда присваивается знаковый бит результата). Эти команды меняют и некоторые другие флаги (см. [5,9]), но это нас интересовать не будет.
Далее рассмотрим команды умножения и деления целых чисел. Формат этих команд накладывает сильные ограничения на месторасположение операндов. Первый операнд всех команд этого класса явно в команде не указывается и находится в фиксированном регистре, принимаемом по умолчанию. В младшей модели семейства есть следующие команды умножения и деления, в них явно задаётся только второй операнд (второй сомножитель или делитель):
mul op2 – беззнаковое умножение,
imul op2 – знаковое умножение,
div op2 – беззнаковое целочисленное деление,
idiv op2 – знаковое целочисленное деление.
Как видим, в отличие от команд сложения и вычитания, умножение и деление знаковых и беззнаковых целых чисел выполняются разными командами (по разным алгоритмам).
В случае с короткими целыми операндами при умножении вычисление производится по формуле:
AX := AL * op2
При делении (операции div и mod понимаются в смысле языка Паскаль):
AL := AX div op2
AH := AX mod op2
В случае с длинными операндами при умножении вычисление производится по формуле:
(DX,AX) := AX * op2
При делении:
AX := (DX,AX) div op2
DX := (DX,AX) mod op2
В этих командах операнд op2 может иметь формат r8,r16,m8 или m16.
Как видим, команды умножения всегда дают точный результат, так как под хранение произведения выделяется в два раза больше места, чем под каждый из сомножителей. Команды деления могут вызывать аварийную ситуацию, если частное не помещается в отведённое для него место, т.е. в регистры AL и AX соответственно. Заметим, что остаток от деления всегда помещается в отводимое для него место на регистрах AH или DX соответственно (докажите это!).
После выполнения команд умножения устанавливаются некоторые флаги, из которых для программиста представляют интерес только флаги переполнения и переноса (CF и OF). Эти флаги устанавливаются по следующему правилу. CF=OF=1, если в произведении столько значащих (двоичных) цифр, что они не помещаются в младшей половине произведения. На практике это означает, что при CF=OF=1 произведение коротких целых чисел не помещается в регистр AL и частично "переползает" в регистр AH, а произведение длинных целых чисел – не помещается в регистре AX и "на самом деле" занимает оба регистра (DX,AX). И наоборот, если CF=OF=0, то в старшей половине произведения (соответственно в регистрах AH и DX) находятся только незначащие двоичные цифры произведения. Другими словами, при CF=OF=0 в качестве результата произведения можно взять его младшую половину.
Команды деления после своего выполнения как-то устанавливают некоторые флаги, но никакой полезной информации из значения этих флагов программист извлечь не может. Можно сказать, что деление "портит" некоторые флаги.
Для написания программ на Ассемблере нам будут полезны также следующие унарные арифметические операции.
neg op1 – взятие обратной величины знакового числа, op1 := -op1;
inc op1 – увеличение (инкремент) аргумента на единицу, op1 := op1+1;
dec op1 – уменьшение (декремент) аргумента на единицу, op1 := op1-1;
Применение этих команд вместо соответствующих по действию команд вычитания и сложения приводит к более компактным программам. Необходимо также отметить, что команды inc и dec, в отличие от эквивалентных им команд add и sub никогда не меняют флаг CF. [9]
Дата добавления: 2015-10-05; просмотров: 1177;