Команды сложения и вычитания

Команды сложения и вычитания реализуют хорошо всем известные арифметические операции. Единственное, что нужно учитывать при использовании этих команд – особенности сложения и вычитания, связанные с представлением чисел в памяти компьютера.

ADD <операнд1>, <операнд2>

SUB <операнд1>, <операнд2>

Команда ADD складывает операнды и записывает их сумму на место первого операнда. Команда SUB вычитает из первого операнда второй и записывает полученную разность на место первого операнда. Операнды должны иметь одинаковый размер. Если первый операнд – регистр, то второй может быть также регистром, ячейкой памяти и непосредственным операндом. Если первый операнд – ячейка памяти, то второй операнд может быть регистром или непосредственным операндом. Возможно сложение и вычитание как знаковых, так и беззнаковых чисел любого размера. Команды меняют флаги AF, CF, OF, PF, SF и ZF.

a dd 45d

b dd -32d

c dd?

mov eax, a

add eax, b

mov c, eax; c = a + b

Команды инкремента и декремента увеличивают и уменьшают на 1 свой операнд.

INC <операнд>

DEC <операнд>

Операндом может быть регистр или ячейка памяти любого размера. Команды меняют флаги AF, OF, PF, SF и ZF. Команды инкремента и декремента выгодны тем, что они занимают меньше места, чем соответствующие команды сложения и вычитания.

inc eax

К арифметическим операциям можно также отнести команду изменения знака:

NEG <операнд>

Операндом может быть регистр или ячейка памяти любого размера. Команда NEG рассматривает свой операнд как число со знаком и меняет знак операнда на противоположный. Команда меняет флаги AF, CF, OF, PF, SF и ZF.

mov ax, 1

neg ax; AX = -1 = ffffh

mov bl, -128

neg bl; BL = -128, OF = 1

Команды умножения и деления

Команды умножения

Сложение и вычитание знаковых и беззнаковых чисел производятся по одним и тем же алгоритмам. Поэтому нет отдельных команд сложения и вычитания для знаковых и беззнаковых чисел. А вот умножение и деление знаковых и беззнаковых чисел производятся по разным алгоритмам, поэтому существуют по две команды умножения и деления.

Для беззнакового умножения используется команда MUL:

MUL <операнд>

Операнд, указываемый в команде, – это один из сомножителей. Он может быть регистром или ячейкой памяти, но не может быть непосредственным операндом.

Местонахождение второго сомножителя и результата фиксировано, и в команде явно не указывается. Если операнд команды MUL имеет размер 1 байт, то второй сомножитель берётся из регистра AL, а результат помещается в регистр AX. Если операнд команды MUL имеет размер 2 байта, то второй сомножитель берётся из регистра AX, а результат помещается в регистровую пару DX:AX. Если операнд команды MUL имеет размер 4 байта, то второй сомножитель берётся из регистра EAX, а результат помещается в регистровую пару EDX:EAX.

Команда меняет флаги CF и OF. Если произведение имеет такой же размер, что и сомножители, то оба флага сбрасываются в 0. Если же размер произведения удваивается относительно размера сомножителей, то оба флага устанавливаются в 1.

x dw 256

mov ax, 105

mul x; AX = AX * x, AX = 26880, CF = OF = 0

mov eax, 500000

mov ebx, 100000

mul ebx; EDX:EAX = EAX * EBX, EDX:EAX = 50000000000, CF = OF = 1

Для знакового умножения используется команда IMUL:

IMUL <операнд>

IMUL <операнд>, <непосредственный операнд>

IMUL <операнд1>, <операнд2>, <непосредственный операнд>

IMUL <операнд1>, <операнд2>

Команда знакового умножения имеет несколько вариантов. Первый соответствует команде MUL – один из сомножителей указывается в команде, второй должен находиться в регистре EAX/AX/AL, а результат помещается в регистры EDX:EAX/DX:AX/AX.

Второй вариант команды IMUL позволяет указать регистр, который будет содержать один из сомножителей. В этот же регистр будет помещён результат. Второй сомножитель указывается непосредственно в команде.

Третий вариант команды IMUL позволяет указать и результат, и оба сомножителя. Однако результат может быть помещён только в регистр, а второй сомножитель может быть только непосредственным операндом. Первый сомножитель может быть регистром или ячейкой памяти.

Четвёртый вариант команды IMUL позволяет указать оба сомножителя. Первый должен быть регистром, а второй – регистром или ячейкой памяти. Результат помещается в регистр, являющийся первым операндом.

Команда IMUL устанавливает флаги так же, как и команда MUL. Однако расширение результата в регистр EDX/DX происходит только при использовании первого варианта команды IMUL. В остальных случаях часть произведения, не помещающаяся в регистр-результат, теряется, даже если в качестве результата указан регистр EAX/AX. При умножении двух 1-байтовых чисел, произведение которых больше байта, но меньше слова, в регистре-результате получается корректное произведение.

mov eax, 5

mov ebx, -7

imul ebx; EAX = ffffffdd, EDX = ffffffff, CF = 0

mov ebx, 3

imul ebx, 6; EBX = EBX * 6

mov ebx, 500000

imul eax, ebx, 100000; EAX = EBX * 100000, старшая часть результата теряется

x dd 40

mov eax, 55

imul eax, x; EAX = EAX * x

Команды деления

Деление, как и умножение, реализуется двумя командами, предназначенными для знаковых и беззнаковых чисел:

DIV <операнд>; Беззнаковое деление

IDIV <операнд>; Знаковое деление

В командах указывается только один операнд – делитель, который может быть регистром или ячейкой памяти, но не может быть непосредственным операндом. Местоположение делимого и результата для команд деления фиксировано.

Если делитель имеет размер 1 байт, то делимое берётся из регистра AX. Если делитель имеет размер 2 байта, то делимое берётся из регистровой пары DX:AX. Если же делитель имеет размер 4 байта, то делимое берётся из регистровой пары EDX:EAX.

Поскольку процессор работает с целыми числами, то в результате деления получается сразу два числа – частное и остаток. Эти два числа также помещаются в определённые регистры. Если делитель имеет размер 1 байт, то частное помещается в регистр AL, а остаток – в регистр AH. Если делитель имеет размер 2 байта, то частное помещается в регистр AX, а остаток – в регистр DX. Если же делитель имеет размер 4 байта, то частное помещается в регистр EAX, а остаток – в регистр EDX.

mov ax, 127

mov bl, 5

div bl; AL = 19h = 25, AH = 02h = 2

mov ax, 127

mov bl, -5

idiv bl; AL = e7h = -25, AH = 02h = 2

mov ax, -127

mov bl, 5

idiv bl; AL = e7h = -25, AH = feh = -2

mov ax, -127

mov bl, -5

idiv bl; AL = 19h = 25, AH = feh = -2

; x = a * b + c

mov eax, a

imul b

add eax, c; Операнды команды сложения вычисляются слева направо

mov x, eax

; x = a + b * c

mov eax, b

imul c

add eax, a; Операнды команды сложения вычисляются справа налево

mov x, eax


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  




Подборка статей по вашей теме: