Tooprogram.ru

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

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

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

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

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

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

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

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

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

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

• 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. Данную команду удобно использовать для подготовки операндов без знака к выполнению арифметических действий.

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

Команды сложения — 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 учитывает возможность заема при выполнении первого вычитания.

Читать еще:  Ассемблер для pic контроллеров

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

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 ВХ; Разделить слово в АХ на слово в ВХ.

Читать еще:  Команда nop ассемблер

Команды ассемблера

Команда mov

Команда mov производит копирование источника в назначение. Рассмотрим примеры:

Внимательно следите, когда вы загружаете адрес переменной, а когда обращаетесь к значению переменной по её адресу. Например:

Команда lea

lea — мнемоническое от англ. Load Effective Address. Синтаксис:

Команда lea помещает адрес источника в назначение. Источник должен находиться в памяти (не может быть непосредственным значением — константой или регистром). Например:

Команды для работы со стеком

Предусмотрено две специальные команды для работы со стеком: push (поместить в стек) и pop (извлечь из стека). Синтаксис:

При описании работы стека мы уже обсуждали принцип работы команд push и pop . Важный нюанс: push и pop работают только с операндами размером 4 или 2 байта. Если вы попробуете скомпилировать что-то вроде

GCC вернёт следующее:

Согласно ABI, в Linux стек выровнен по long . Сама архитектура этого не требует, это только соглашение между программами, но не рассчитывайте, что другие библиотеки подпрограмм или операционная система захотят работать с невыровненным стеком. Что всё это значит? Если вы резервируете место в стеке, количество байт должно быть кратно размеру long , то есть 4. Например, вам нужно всего 2 байта в стеке для short , но вам всё равно придётся резервировать 4 байта, чтобы соблюдать выравнивание. А теперь примеры:

Интересный вопрос: какое значение помещает в стек вот эта команда

Если ещё раз взглянуть на алгоритм работы команды push , кажется очевидным, что в данном случае она должна поместить уже уменьшенное значение %esp . Однако в документации Intel 1 Intel® 64 and IA-32 Architectures Software Developer’s Manual, 4.1 Instructions (N-Z), PUSH сказано, что в стек помещается такое значение %esp , каким оно было до выполнения команды — и она действительно работает именно так.

Арифметика

Арифметических команд в нашем распоряжении довольно много. Синтаксис:

  • inc : увеличивает операнд на 1.
  • dec : уменьшает операнд на 1.
  • add : приёмник = приёмник + источник (то есть, увеличивает приёмник на источник).
  • sub : приёмник = приёмник — источник (то есть, уменьшает приёмник на источник).

Команда mul имеет только один операнд. Второй сомножитель задаётся неявно. Он находится в регистре %eax , и его размер выбирается в зависимости от суффикса команды ( b , w или l ). Место размещения результата также зависит от суффикса команды. Нужно отметить, что результат умножения двух -разрядных чисел может уместиться только в -разрядном регистре результата. В следующей таблице описано, в какие регистры попадает результат при той или иной разрядности операндов.

КомандаВторой сомножительРезультат
mulb%al16 бит: %ax
mulw%ax32 бита: младшая часть в %ax , старшая в %dx
mull%eax64 бита: младшая часть в %eax , старшая в %edx

Давайте подумаем, каким будет результат выполнения следующего кода на Си:

Большинство сразу скажет, что результат (250 + 14 = 264) больше, чем может поместиться в одном байте. И что же напечатает программа? 8. Давайте рассмотрим, что происходит при сложении в двоичной системе.

Получается, что результат занимает 9 бит, а в переменную может поместиться только 8 бит. Это называется переполнением — перенос из старшего бита результата. В Си переполнение не может быть перехвачено, но в микропроцессоре эта ситуация регистрируется, и её можно обработать. Когда происходит переполнение, устанавливается флаг cf . Команды условного перехода jc и jnc анализируют состояние этого флага. Команды условного перехода будут рассмотрены далее, здесь эта информация приводится для полноты описания команд.

Этот код выдаёт правильную сумму в регистре %ax с учётом переполнения, если оно произошло. Попробуйте поменять числа в строках 2 и 3.

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

Обновл. 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:

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

Рассмотрим 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:

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