3.3. Команды сложения и вычитания
Команды сложения и вычитания реализуют хорошо всем известные арифметические операции. Единственное, что нужно учитывать при использовании этих команд – особенности сложения и вычитания, связанные с представлением чисел в памяти компьютера.
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
3.4. Команды умножения и деления
3.4.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
Do'stlaringiz bilan baham: |