Tooprogram.ru

Компьютерный справочник
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Ассемблер арифметические операции

Арифметические команды Ассемблера

Команды сложения — ADD, ADC

Команды ADD (add — сложить) и ADC (add with carry- сложить с переносом) могут складывать как 8-, так и 16-битовые операнды.

Команда ADD складывает содержимое операнда-источника и операнда-приемника и помещает результат в операнд-приемник.

Формат команды: ADD приемник, источник

В символической нотации ее действия можно описать следующим образом: приемник := приемник + источник (в приемник записывается сумма содержимого приемника и источника).

Команда ADC делает то же, что и команда ADD, но складывает не два, а три слагаемых: приемник, источник и флаг переноса.

Формат команды: ADC приемник, источник + CF

В символической нотации ее действия можно описать как:

приемник := приемник + источник + содержимое флага переноса.

Перенос при сложении двоичных чисел аналогичен переносу при сложении десятичных чисел в столбик. Когда ЭВМ складывает двоичные числа и сумма не помещается в операнде-приемнике, то генерируется перенос. Как известно, 8-битовый регистр может содержать значения без знака в диапазоне от 0 до 255. Если мы, например, выполним двоичное сложение чисел 250 и 10, то получим следующий результат:

1111 1010; двоичное представление числа 250.

0000 1010; двоичное представление числа 10.

1 0000 0100; двоичное представление суммы, равной 260.

Результат верен, но занимает 9 двоичных битов. Если использовались 8 — битовые регистры, то младшие 8 битов будут занесены в регистр-приемник, а девятый бит- во флаг переноса CF.

Теперь понятно, почему микропроцессор 8086 имеет две разные команды сложения. Одна из них (ADD) может складывать значения, представляемые байтами или словами, а также младшие части значений повышенной точности. Другая команда (ADC) используется для сложения старших частей значений повышенной точности.

Складываемые операнды могут находиться в памяти, регистре или иметь непосредственное значение. Например:

ADD АХ,MEM_WORD; прибавить содержимое ячейки памяти к регистру,

ADD MEM_WORD,AX; или наоборот, прибавить содержимое регистра к ячейки памяти.

ADD AL, 10; прибавить константу к содержимому регистра.

ADD MEM_BYTE,8H; сложить константу и содержимое ячейки памяти.

Допускается большинство возможных комбинаций, но нельзя складывать содержимое двух ячеек памяти или использовать в качестве приемника непосредственное значение (число).

Команды ADD и ADC могут воздействовать на следующие шесть флагов:

флаг переноса CF равен 1, если результат сложения не помещается в операн­де-приемнике, в противном случае он равен 0;

флаг четности PF равен 1, если результат имеет четное число битов со значением 1, в противном случае он равен 0;

вспомогательный флаг переноса AF равен 1, если результат сложения десятичных чисел требует коррекции;

флаг нуля ZF равен 1, если результат равен 0;

флаг знака SF равен 1, если результат отрицателен (старший бит равен 1), в противном случае он равен 0;

флаг переполнения OF равен 1, если слагаемое двух чисел одного знака превышает диапазон допустимых значений приемника в обратном коде, а сам приемник при этом меняет знак. Иначе флаг OF равен 0.

Команда увеличения значения приемника на единицу – INC

Команда INC(increment — прирастить) добавляет 1 к содержимому регистра или ячейки памяти, но в отличие от команды ADD не воздействует на флаг переноса CF. Формат команды: INC приемник.

Команда INC удобна для увеличения значений счетчиков в циклах команд. Ее можно использовать и для увеличения значения индексного регистра при доступе к последовательно расположенным ячейкам памяти. Операнд интерпретируется как число без знака.

INC CX; увеличить значение 16-битового

INC AL; или 8-битового регистра на единицу.

INC MEM_BYTE; увеличить значение байта

INC MEM_WORD; или слова памяти на единицу.

Не допускается использовать в качестве операнда непосредственное значение.

Команды вычитания — SUB, и вычитания с заемом SBB

Команды SUB (substract — вычесть) и SBB (substract with borrow — вычесть с заемом) аналогичны соответственно командам сложения ADD и ADC, только при вычитании флаг переноса CF действует как признак заема. Формат команды: SUB приемник,источник;

Команда SUB вычитает операнд -источник из операнда -приемника и помещает результат в приемник, в символической нотации:

приемник := приемник – источник.

Команда SBB делает то же самое, но дополнительно вычитает из приемника значение флага переноса CF:

SUB приемник,источник – СF;

Приемник := приемник — источник — содержимое флага переноса.

Как и в случае сложения, команды SUB и SBB выполняют две отдельные функции. Первая команда вычитает числа размером в байт или слово, а также младшие биты чисел повышенной точности (младшая часть числа расположена в регистре АХ, а старшая часть в регистре DX). Вторая команда вычитает старшие биты чисел повышенной точности. Например, команда SUB AX,CX; вычитает содержимое регистра СХ из содержимого регистра АХ и возвращает результат в регистр АХ.

Если размеры операндов превышают 16 бит, то необходимо применить следующую последовательность команд:

SUB АХ,CX; Вычесть младшие 16 бит;

SBB BX,DX; а затем старшие 16 бит.

Здесь мы вычитаем из 32-битового числа, помещенного в регистры АХ и ВХ, 32-битовое число, находящееся в регистрах СХ и DX. При вычитании содержимого регистра DX из содержимого регистра ВХ команда SBB учитывает возможность заема при выполнении первого вычитания.

Можно вычитать из содержимого регистра содержимое ячейки памяти (и наоборот) или вычитать из содержимого регистра либо ячейки памяти непосредственное значение. Примеры допустимых команд:

SUB АХ, MEM; Вычесть из регистра содержимое ячейки памяти.

SUB MEM [BX],AX; Вычесть из ячейки памяти регистр.

SUB AL,1O; Вычесть константу из регистра.

SUB MEM_BYTE,OFh; Вычесть константу из ячейки памяти.

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

Команды SUB и SBB могут воздействовать на шесть флагов следующим образом:

· устанавливают флаг переноса CF в 1, если требуется заем, в противном случае он равен 0;

· устанавливают флаг четности PF в 1, если результат вычитания имеет четное число битов со значением 1, в противном случае он равен 0;

· устанавливают вспомогательный флаг переноса AF в 1, если результат вычитания десятичных чисел требует коррекции, в противном случае он равен 0;

· устанавливают флаг нуля ZF в 1, если результат равен 0, в противном случае он равен 0;

· устанавливают флаг знака SF в 1, если результат отрицателен (старший бит равен 1), в противном случае флаг равен 0;

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

Флаги SF и OF имеют смысл только при вычитании чисел со знаком, а флаг AF- только при вычитании десятичных чисел.

Команда уменьшения содержимого приемника — DEC

КомандаDEC приемник (decrement-уменьшить) вычитает 1 из содержимого регистра или ячейки памяти, но при этом (в отличие от команды SUB) не воздействует на флаг переноса CF.

Команда DEC часто используется в циклах для уменьшения значения счетчика до тех пор, пока оно не станет нулевым или отрицательным. Ее можно использовать также для уменьшения значения индексного регистра или указателя при доступе к последовательно расположенным ячейкам памяти. Например:

Читать еще:  Переменные в ассемблере

DEC CX; Уменьшить значение 16-битового,

DEC AL; или 8-битового регистра.

DEC MEM_BYTE; Уменьшить значение байтовой,

DEC MEM_WORD[BX]; или словной ячейки памяти.

Команды деления — DIV, IDIV

КомандаDIV (divide — разделить) выполняет деление чисел без знака, а команда IDIV (integer divide — разделить целые числа) выполняет деление чисел со знаком. Эти команды имеют формат:

DIV источник; где источник — делитель размером в байт или слово,

IDIV источник;находящийся в регистре общего назначения или в ячейке памяти.

Обратите внимание на следующее:

1. Делимое по отношению к делителю должно иметь двойной размер.

2. Делимое всегда должно находиться в регистре АХ (при делении на 8-битовое число) или в регистрах DX и АХ (при делении на 16-битовое число).

3. Результаты команды возвращаются следующим образом:

· если операнд-источник представляет собой байт, то частное возвращается в регистр AL, а остаток в регистр АН;

· если операнд-источник представляет собой слово, то частное возвращается в регистр АХ, а остаток — в регистр DX.

Обе команды оставляют состояние флагов неопределенными, но если частное не помещается в регистре-приемнике (AL или АХ), то микропроцессор генерирует прерывание типа 0 (деление на 0).

4. Переполнение результата деления возникает при следующих условиях:

· делитель равен 0;

· при делении байтов без знака делимое, по меньшей мере, в 256 раз превышает делитель;

· при делении слов без знака делимое, по меньшей мере, в 65 536 раз превышает делитель;

· при делении байтов со знаком частное лежит вне диапазона -128 до +127;

· при делении слов со знаком частное лежит вне диапазона от

Приведем несколько типичных примеров операций деления:

DIV BX; Разделить DX:AX на ВХ, без знака.

DIV MEM_BYTE; Разделить АХ на байт памяти, без знака.

IDIV DL; Разделить АХ на DL со знаком.

IDIV MEM WORD; Разделить DX:AX на слово памяти, со знаком.

Команды DIV и IDIV не позволяют прямо разделить на непосредственное значе­ние, так как процессор не может определить тип данных делителя.

Команды умножения — MUL, IMUL

Команда MUL (multiply-умножить) умножает числа без знака, a IMUL(integer multiply-умно­жить) умножает целые числа со знаком. Множимое и множитель у обеих команд должны быть данные одного типа, то есть байты, слова, двойные слова и т. д.

Эти команды имеют следующий формат:

MUL источник; гдеисточник — регистр общего назначения,

IMUL источник; или ячейка памяти размером в байт или слово.

В качестве первого операнда (множимого) команды MUL и IMUL используют содер­жимое регистра AL (при операциях над байтами) или регистра АХ (при операциях над словами). Произведение имеет двойной размер и возвращается следующим образом:

· умножение байтов -возвращает 16-битовое произведение в регистры АН (старший байт) и AL (младший байт);

· умножение слов -возвращает 32- битовое произведение в регистры DX (старшее слово) и АХ (младшее слово). Таким образом, размер произведения n— битных сомножителей равен 2n.

После исполнения команды MUL флаги CF и OF равны 0, если старшая половина произведения равна 0; в противном случае оба этих флага равны 1.

После исполнения команды IMUL флаги CF и OF равны 0, если старшая половина произведения представляет собой лишь расширение знака младшей половины. В противном случае они равны 1.

Несколько примеров умножения:

MUL BX; Умножить АХ на без ВХ знака.

MUL MEM_BYTE; Умножить содержимое ячейки памяти на AL.

IMUL DL; Умножить DL на AL со знаком.

IMUL MEM_WORD; Умножить ячейку памяти на АХ со знаком.

Команды MUL и IMUL не дозволяют в качестве операнда использовать непосредственное число.

Команды преобразования типов данных – CBW, CWD,CDQ

Существуют команды, позволяющие выполнять операции над смешанными данными за счет удвоения размера операнда со знаком.

Команда CBW (convert byte to wordпреобразовать байт в слово) копирует седьмой бит регистра AL во всех битах регистра АН.

Команда CWD (convert word to double word – преобразовать слово в двойное слово) копирует 15-й бит регистра АХ во всех битах регистра DX.

Команда CWDE копирует 15-й бит регистра АХ во всех битах регистра ЕАХ.

Команда CDQ – преобразовать двойное слово в учетверенное слово, копирует 31- й бит EAX во все битах EDX.

Таким образом, команда CBW позволяет сложить байт и слово, вычесть слово из байта и т.д. Аналогично команда CWD позволяет разделить слово на слово. Приведем несколько примеров:

CBW; Расширить AL до AX (байт до слова).

ADD AX,BX; Сложить байт в AL со словом в ВХ.

CBW; Расширить AL до AX.
IMUL ВХ; Умножить содержимое AL на содержимое ВХ.

CWD; Расширить AХ в DX (слово до двойного слова).

IDIV ВХ; Разделить слово в АХ на слово в ВХ.

Ассемблер. Арифметические инструкции

Обновл. 20 Окт 2019 |

В этом уроке мы будем разбираться с арифметическими инструкциями в ассемблере на примере INC, DEC, ADD, SUB и пр.

Инструкция INC

Инструкция INC (от англ. «INCREMENT») используется для увеличения операнда на единицу. Она работает с одним операндом, который может находиться либо в регистре, либо в памяти.

Синтаксис инструкции INC:

Операндом место_назначения может быть 8-битный, 16-битный или 32-битный операнд.

Инструкция DEC

Инструкция DEC (от англ. «DECREMENT») используется для уменьшения операнда на единицу. Она работает с одним операндом, который может находиться либо в регистре, либо в памяти.

Синтаксис инструкции DEC:

Операндом место_назначения может быть 8-битный, 16-битный или 32-битный операнд.

Инструкции ADD и SUB

Инструкции ADD и SUB используются для выполнения простого сложения/вычитания двоичных данных размером в byte, word и doubleword, то есть для сложения или вычитания 8-битных, 16-битных или 32-битных операндов, соответственно.

Синтаксис инструкций ADD и SUB:

ADD/SUB место_назначения, источник

Инструкции ADD/SUB могут выполняться между:

регистром и регистром;

памятью и регистром;

регистром и памятью;

памятью и константами.

Однако, как и другие инструкции, операции типа память-в-память невозможны с использованием инструкций ADD/SUB. Операции ADD или SUB устанавливают или сбрасывают флаги переполнения и переноса.

В следующем примере мы спрашиваем у пользователя два числа, сохраняем их в регистрах EAX и EBX, затем выполняем операцию сложения, сохраняем результат в ячейке памяти res и выводим его на экран:

Результат выполнения программы выше:

Enter a digit:
3
Please enter a second digit:
4
The sum is:
7

Ниже рассмотрен пример, в котором, за счёт того, что значения переменных для арифметических выражений прописаны в самом коде программы, можно получить код программы короче и проще:

Результат выполнения программы выше:

Инструкции MUL и IMUL

Есть две инструкции для умножения двоичных данных:

инструкция MUL (от англ. «MULTIPLY») обрабатывает данные unsigned;

инструкция IMUL (от англ. «INTEGER MULTIPLY») обрабатывает данные signed.

Обе инструкции влияют на флаги переноса и переполнения.

Синтаксис инструкций MUL/IMUL:

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

Читать еще:  Язык си char

Рассмотрим 3 разных сценария:

Сценарий №1: Когда перемножаются 2 значения типа byte — множимое находится в регистре AL, а множителем является значение типа byte в памяти или в другом регистре. Результат произведения находится в AX. Старшие 8 бит произведения хранятся в AH, а младшие 8 бит — хранятся в AL:

Сценарий №2: Когда перемножаются 2 значения типа word — множимое должно быть в регистре AX, а множителем является значение типа word в памяти или в другом регистре. Например, для такой инструкции, как MUL DX , вы должны сохранить множитель в DX, а множимое — в AX. В результате получится значение типа doubleword для которого понадобятся два регистра. Часть высшего порядка (крайняя слева) сохраняется в DX, а часть нижнего порядка (крайняя справа) — сохраняется в AX:

Сценарий №3: Когда перемножаются 2 значения типа doubleword — множимое должно находится в EAX, а множителем является значение типа doubleword, хранящееся в памяти или в другом регистре. Результат умножения сохраняется в регистрах EDX и EAX. Биты старшего порядка сохраняются в регистре EDX, а биты младшего порядка — сохраняются в регистре EAX:

Ассемблер арифметические операции

Микропроцессор может выполнять целочисленные операции и операции с плавающей точкой. Для этого в его архитектуре есть два отдельных блока:

•устройство для выполнения целочисленных операций;

•устройство с плавающей точкой.

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

. Для большинства задач, использующих язык ассемблера, достаточно целочисленной арифметики.

Сложение беззнаковых чисел

Микропроцессор выполняет сложение операндов по правилам сложения двоичных чисел.

• add операнд1,операнд2 — команда сложения с принципом действия:

операнд1 = операнд1 + операнд2

· xadd назначение,источник — обмен местами и сложение.

Команда позволяет выполнить последовательно два действия:

•обменять значения назначение и источник;

•поместить на место операнда назначение сумму:

назначение = назначение + источник.

. В операции сложения должны участвовать операнды одного формата ( b — b , w — w )

. Возможны сочетания регистр — регистр

регистр — непосредственный операнд

неп. Операнд — регистр

. Операция память — память выполняется через промежуточный регистр

Пример1 Вычисление суммы двух чисел

• inc операнд — операция инкремента, то есть увеличения значения операнда на 1;

операнд = операнд +1

. Операнд м.б. регистром или адресом памяти и . не м.б. непоср.операндом

Пример2. Увеличение числа на 1

Особые ситуации, которые могут возникать при сложении :

1) значение результата превышает размерности поля операнда

для фиксирования ситуации выхода за разрядную сетку результата в микропроцессоре предусмотрено специальное средство: флаг переноса CF ( curry flag ) . Он располагается в бите 0 регистра флагов eflags/flags. Именно установкой этого флага фиксируется факт переноса единицы из старшего разряда операнда. ( CF =1)

Например, при сложении операндов размером в байт результат не должен превышать число 255. Если это происходит, то результат оказывается неверным.

Например, выполним сложение: 254 + 5 = 259 в двоичном виде. 11111110 + 0000101 = 1 00000011. Результат вышел за пределы восьми бит и правильное его значение укладывается в 9 бит, а в 8-битовом поле операнда осталось значение 3, что, конечно, неверно.

Т.е. если при сложении двух 8-битовых чисел результат занимает 9 битов, то значение старшего 9 бита запоминается во флажке CF .

. Программист должен предусматривать возможность такого исхода операции сложения Необходимо включать участки кода после операции сложения, в которых анализируется флаг cf.

Анализ этого флага можно провести различными способами.

Например, использовать команду условного перехода

jc ; Переход на метку если cf = 1

jnc ; Переход на метку если cf = 0

• adc операнд_1,операнд_2 — команда сложения с учетом флага переноса cf.

операнд_1 = операнд_1 + операнд_2 + значение_cf

это команда сложения, учитывающая перенос единицы из старшего разряда.

Пример 3. Вычисление суммы чисел

add al,a ; результат сложения выходит за границы операнда.

jnc m1 ; проверяет состояние флага cf — если нет переноса, то перейти на m1

adc ah,0 ;в ax сумма с учетом переноса в старший разряд

mov ax,4c00h ;стандартный выход

При сложении чисел со знаком может произойти особая ситуация

2) результат выходит из диапазона допустимых значений

Переполнение регистрируется с помощью флага переполнения of.

Дополнительно к флагу of при переносе из старшего разряда устанавливается в 1 и флаг переноса cf.

Проанализировать флаг of можно командами условного перехода jo jno .

учет особых ситуаций должен производиться самим программистом. .

К командам вычитания относятся следующие:

•sub операнд_1,операнд_2 — команда вычитания; ее принцип действия:

операнд_1 = операнд_1 – операнд_2

•sbb операнд_1,операнд_2 — команда вычитания с учетом заема (флага cf ):

(subtract with borrow — вычитание с заемом )

операнд_1 = операнд_1 – операнд_2 – значение_cf

флаг cf выполняет роль индикатора заема 1 из старшего разряда при вычитании чисел.

. Таким образом, после команды вычитания чисел без знака нужно анализировать состояние флага cf. Если он установлен в 1, то это говорит о том, что произошел заем из старшего разряда и результат получился в дополнительном коде.

•dec операнд — операция декремента, то есть уменьшения значения операнда на 1;

Пример 4. Проверка при вычитании чисел без знака

.code ; сегмент кода

main: ;точка входа в программу

sub al,10 ; вычитание — результат получается в дополнительном коде (отрицательный)

jnc m1 ;нет переноса?

neg al ;в al модуль результата

mov ax,4c00h ;стандартный выход

end main ;конец программы

Для того чтобы преобразовать результат к нормальному виду (получить его модуль), применяется команда neg, с помощью которой получается дополнение операнда. В нашем случае мы получили дополнение дополнения или модуль отрицательного результата. А тот факт, что это на самом деле число отрицательное, отражен в состоянии флага cf. Дальше все зависит от алгоритма обработки.

neg операнд — отрицание с дополнением до двух.

Команда выполняет инвертирование значения операнд.

операнд = 0 – операнд, то есть вычитает операнд из нуля.

Команду neg операнд можно применять:

•для смены знака;

•для выполнения вычитания из константы.

Дело в том, что команды sub и sbb не позволяют вычесть что-либо из константы, так как константа не может служить операндом-приемником в этих операциях. Поэтому данную операцию можно выполнить с помощью двух команд:

neg ax ;смена знака (ax)

add ax,340 ;фактически вычитание: (ax)=340-(ax)

1. Сложение и вычитание знаковых и беззнаковых чисел проводятся по одним и тем же алгоритмам. ПК не знает какие числа (знаковые или беззнаковые) он складывает и вычитает, поэтому фиксирует в флагах CF OF особенности операций. Какие числа обрабатываются знает программист. Если предполагается, что работа идет с беззнаковыми числами, необходимо производить анализ флага CF , а OF не надо. Если предполагается, что работа идет со знаковыми числами, необходимо производить анализ флага О F , а С F не надо.

2. К оманды INC DEC занимают только один байт и работают быстрее, чем команды ADD SUB , занимающие три байта.

3. Команды ADD SUB устанавливают флажок переноса, а INC DEC нет

4. Кроме флагов cf и of в регистре eflags есть еще несколько флагов, которые можно использовать с двоичными арифметическими командами:

Читать еще:  Язык си машинно ориентированный

•zf — флаг нуля, который устанавливается в 1, если результат операции равен 0, и в 1, если результат не равен 0;

•sf — флаг знака, значение которого после арифметических операций (и не только) совпадает со значением старшего бита результата, то есть с битом 7, 15 или 31. Таким образом, этот флаг можно использовать для операций над числами со знаком.

Что делать, если размеры операндов, участвующих в арифметических операциях, разные?

Например, предположим, что в операции сложения один операнд является словом, а другой занимает двойное слово. Выше сказано, что в операции сложения должны участвовать операнды одного формата. Если числа без знака, то выход найти просто. В этом случае можно на базе исходного операнда сформировать новый (формата двойного слова), старшие разряды которого просто заполнить нулями. Сложнее ситуация для чисел со знаком: как динамически, в ходе выполнения программы, учесть знак операнда? Для решения подобных проблем в системе команд микропроцессора есть так называемые команды преобразования типа. Эти команды расширяют байты в слова, слова — в двойные слова и двойные слова — в учетверенные слова (64-разрядные значения). Команды преобразования типа особенно полезны при преобразовании целых со знаком, так как они автоматически заполняют старшие биты вновь формируемого операнда значениями знакового бита старого объекта. Эта операция приводит к целым значениям того же знака и той же величины, что и исходная, но уже в более длинном формате. Подобное преобразование называется операцией распространения знака.

Существуют два вида команд преобразования типа:

1. Команды без операндов — эти команды работают с фиксированными регистрами:

· cbw (Convert Byte to Word) — команда преобразования байта (в регистре al) в слово (в регистре ax) путем распространения значения старшего бита al на все биты регистра ah;

· cwd (Convert Word to Double) — команда преобразования слова (в регистре ax) в двойное слово (в регистрах dx:ax) путем распространения значения старшего бита ax на все биты регистра dx;

· cwde (Convert Word to Double) — команда преобразования слова (в регистре ax) в двойное слово (в регистре eax) путем распространения значения старшего бита ax на все биты старшей половины регистра eax;

· cdq (Convert Double Word to Quarter Word) — команда преобразования двойного слова (в регистре eax) в учетверенное слово (в регистрах edx:eax) путем распространения значения старшего бита eax на все биты регистра edx.

2. Команды movsx и movzx, относящиеся к командам обработки строк. Эти команды обладают полезным свойством в контексте нашей проблемы:

•movsx операнд_1,операнд_2 — переслать с распространением знака. Расширяет 8 или 16-разрядное значение операнд_2, которое может быть регистром или операндом в памяти, до 16 или 32-разрядного значения в одном из регистров, используя значение знакового бита для заполнения старших позиций операнд_1. Данную команду удобно использовать для подготовки операндов со знаками к выполнению арифметических действий;

•movzx операнд_1,операнд_2 — переслать с расширением нулем. Расширяет 8 или 16-разрядное значение операнд_2 до 16 или 32-разрядного с очисткой (заполнением) нулями старших позиций операнд_2. Данную команду удобно использовать для подготовки операндов без знака к выполнению арифметических действий.

Ассемблер арифметические операции

7.1. Сложение и вычитание.

7.1.1. ADD – команда для сложения двух чисел. Она работает как с числами со знаком, так и без знака.

Логика работы команды:

Возможные сочетания операндов для этой команды аналогичны команде MOV .

По сути дела, это – команда сложения с присвоением, аналогичная принятой в языке C / C ++:

Операнды должны иметь одинаковый размер. Результат помещается на место первого операнда.

После выполнения команды изменяются флаги, по которым можно определить характеристики результата:

  1. Флаг CF устанавливается, если при сложении произошёл перенос из старшего разряда. Для беззнаковых чисел это будет означать, что произошло переполнение и результат получился некорректным.
  2. Флаг OF обозначает переполнение для чисел со знаком.
  3. Флаг SF равен знаковому биту результата (естественно, для чисел со знаком, а для беззнаковых он равен старшему биту и особо смысла не имеет).
  4. Флаг ZF устанавливается, если результат равен 0.
  5. Флаг PF — признак чётности, равен 1, если результат содержит нечётное число единиц.

add ax ,5 ; AX = AX + 5

add dx,cx ;DX = DX + CX

add dx,cl ;Ошибка: разный размер операндов.

7.1.2. SUB — команда для вычитания одного числа из другого. Она работает как с числами со знаком, так и без знака.

Логика работы команды:

Возможные сочетания операндов для этой команды аналогичны команде MOV .

По сути дела, это – команда вычитания с присвоением, аналогичная принятой в языке C / C ++:

Операнды должны иметь одинаковый размер. Результат помещается на место первого операнда.

На самом деле вычитание в процессоре реализовано с помощью сложения. Процессор меняет знак второго операнда на противоположный, а затем складывает два числа.

sub ax ,13 ; AX = AX — 13

sub ax , bx ; AX = AX + BX

sub b x,cl ;Ошибка: разный размер операндов.

7.1.3. Инкремент и декремент. Очень часто в программах используется операция прибавления или вычитания единицы. Прибавление единицы называется инкрементом, а вычитание — декрементом. Для этих операций существуют специальные команды процессора: INC и DEC. Эти команды не изменяют значение флага CF.

Эти команды содержит один операнд и имеет следующий синтаксис:

Логика работы команд:

В качестве инкремента допустимы регистры и память: reg , mem .

inc ax ; AX = AX + 1

dec ax ; AX = AX — 1

7.1.4. NEG – команда для изменения знака операнда.

Логика работы команды:

В качестве декремента допустимы регистры и память: reg , mem .

7.2. Сложение и вычитание с переносом.

В системе команд процессоров x86 имеются специальные команды сложения и вычитания с учётом флага переноса (CF). Для сложения с учётом переноса предназначена команда ADC, а для вычитания — SBB. В общем, эти команды работают почти так же, как ADD и SUB, единственное отличие в том, что к младшему разряду первого операнда прибавляется или вычитается дополнительно значение флага CF.

Они позволяют выполнять сложение и вычитание многобайтных целых чисел, длина которых больше, чем разрядность регистров процессора (в нашем случае 16 бит). Принцип программирования таких операций очень прост — длинные числа складываются (вычитаются) по частям. Младшие разряды складываются(вычитаются) с помощью обычных команд ADD и SUB, а затем последовательно складываются(вычитаются) более старшие части с помощью команд ADC и SBB. Так как эти команды учитывают перенос из старшего разряда, то мы можем быть уверены, что ни один бит не потеряется. Этот способ похож на сложение(вычитание) десятичных чисел в столбик.

На следующем рисунке показано сложение двух двоичных чисел командой ADD:

При сложении происходит перенос из 7-го разряда в 8-й, как раз на границе между байтами. Если мы будем складывать эти числа по частям командой ADD, то перенесённый бит потеряется и в результате мы получим ошибку. К счастью, перенос из старшего разряда всегда сохраняется в флаге CF. Чтобы прибавить этот перенесённый бит, достаточно применить команду ADC:

//Сложение двух чисел с учетом переноса: FFFFFFAA + FFFF

Ссылка на основную публикацию
Adblock
detector