Tooprogram.ru

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

Сложение чисел ассемблер

Арифметические операции над двоично-десятичными числами

У вас справедливо может возникнуть вопрос: а зачем нужны BCD-числа? Ответ может быть следующим: BCD-числа нужны в деловых приложениях, то есть там, где числа должны быть большими и точными. Как мы уже убедились на примере двоичных чисел, операции с такими числами довольно проблематичны для языка ассемблера. К недостаткам использования двоичных чисел можно отнести следующие:

  • значения величин в формате слова и двойного слова имеют ограниченный диапазон. Если программа предназначена для работы в области финансов, то ограничение суммы в рублях величиной 65 536 (для слова) или даже 4 294 967 296 (для двойного слова) будет существенно сужать сферу ее применения (да еще в наших экономических условиях — тут уж никакая деноминация не поможет);
  • наличие ошибок округления. Представляете себе программу, работающую где-нибудь в банке, которая не учитывает величину остатка при действиях с целыми двоичными числами и оперирует при этом миллиардами? Не хотелось бы быть автором такой программы. Применение чисел с плавающей точкой не спасет — там существует та же проблема округления;
  • представление большого объема результатов в символьном виде (ASCII-коде). Деловые программы не просто выполняют вычисления; одной из целей их использования является оперативная выдача информации пользователю. Для этого, естественно, информация должна быть представлена в символьном виде. Перевод чисел из двоичного кода в ASCII- код, как мы уже видели, требует определенных вычислительных затрат. Число с плавающей точкой еще труднее перевести в символьный вид. А вот если посмотреть на шестнадцатеричное представление неупакованной десятичной цифры (в начале нашего занятия) и на соответствующий ей символ в таблице ASCII, то видно что они отличаются на величину 30h. Таким образом, преобразование в символьный вид и обратно получается намного проще и быстрее.

Наверняка, вы уже убедились в важности овладения хотя бы основами действий с десятичными числами. Далее рассмотрим особенности выполнения основных арифметических операций с десятичными числами. Для предупреждения возможных вопросов отметим сразу тот факт, что отдельных команд сложения, вычитания, умножения и деления BCD-чисел нет. Сделано это по вполне понятным причинам: размерность таких чисел может быть сколь угодно большой. Складывать и вычитать можно двоично-десятичные числа как в упакованном формате, так и в неупакованном, а вот делить и умножать можно только неупакованные BCD-числа. Почему это так, будет видно из дальнейшего обсуждения.

Арифметические действия над неупакованными BCD-числами


Сложение неупакованных BCD-чисел

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

Назначение этих команд — в корректировке результата работы обычных арифметических команд для случаев когда операнды в них являются BCD-числами.

В случае вычитания в примере 10 видно, что полученный результат нужно корректировать. Для коррекции операции сложения двух однозначных неупакованных BCD-чисел в системе команд микропроцессора существует специальная команда

aaa (ASCII Adjust for Addition) — коррекция результата сложения для представления в символьном виде.

Эта команда не имеет операндов. Она работает неявно только с регистром al и анализирует значение его младшей тетрады:

  • если это значение меньше 9, то флаг cf сбрасывается в 0 и осуществляется переход к следующей команде;
  • если это значение больше 9, то выполняются следующие действия:
    • к содержимому младшей тетрады al (но не к содержимому всего регистра!) прибавляется 6, тем самым значение десятичного результата корректируется в правильную сторону;
    • флаг cf устанавливается в 1, тем самым фиксируется перенос в старший разряд, для того чтобы его можно было учесть в последующих действиях.

Так, в примере 10, предполагая, что значение суммы 0000 1101 находится в al, после команды aaa в регистре будет 1101 + 0110= 0011, то есть двоичное 0000 0011 или десятичное 3, а флаг cf установится в 1, то есть перенос запомнился в микропроцессоре. Далее программисту нужно будет использовать команду сложения adc, которая учтет перенос из предыдущего разряда. Приведем пример программы сложения двух неупакованных BCD-чисел. В листинге 8 есть несколько интересных моментов, над которыми есть смысл поразмыслить. Начнем с описания BCD-чисел. Из строк 5 и 6 видно, что порядок их ввода обратен нормальному, то есть цифры младших разрядов расположены по меньшему адресу. Но это вполне логично по нескольким причинам:

  • во-первых, такой порядок удовлетворяет общему принципу представления данных для микропроцессоров Intel;
  • во-вторых, это очень удобно для поразрядной обработки неупакованных BCD-чисел, так как каждое из них занимает один байт.

Хотя, как уже было отмечено, программист сам волен выбирать способ описания BCD-чисел в сегменте данных. Строки 14–15 содержат команды, которые складывают цифры в очередных разрядах BCD-чисел, при этом учитывается возможный перенос из младшего разряда. Команда aaa в строке 16 корректирует результат сложения, формируя в al BCD-цифру и, при необходимости, устанавливая в 1 флаг cf. Строка 20 учитывает возможность переноса при сложении цифр из самых старших разрядов чисел. Результат сложения формируется в поле sum, описанном в строке 7.

Вычитание неупакованных BCD-чисел

aas (ASCII Adjust for Substraction) — коррекция результата вычитания для представления в символьном виде.

Команда aas также не имеет операндов и работает с регистром al, анализируя его младшую тетраду следующим образом:

  • если ее значение меньше 9, то флаг cf сбрасывается в 0 и управление передается следующей команде;
  • если значение тетрады в al больше 9, то команда aas выполняет следующие действия:
    1. из содержимого младшей тетрады регистра al (заметьте — не из содержимого всего регистра) вычитает 6;
    2. обнуляет старшую тетраду регистра al;
    3. устанавливает флаг cf в 1, тем самым фиксируя воображаемый заем из старшего разряда.

Понятно, что команда aas применяется вместе с основными командами вычитания sub и sbb. При этом команду sub есть смысл использовать только один раз, при вычитании самых младших цифр операндов, далее должна применяться команда sbb, которая будет учитывать возможный заем из старшего разряда. В листинге 9 мы обходимся одной командой sbb, которая в цикле производит поразрядное вычитание двух BCD-чисел. Данная программа не требует особых пояснений, когда уменьшаемое больше вычитаемого. Поэтому обратите внимание на строку 24. С ее помощью мы предусматриваем случай, когда после вычитания старших цифр чисел был зафиксирован факт заема. Это говорит о том, что вычитаемое было больше уменьшаемого, в результате чего разность будет неправильной. Эту ситуацию нужно как-то обработать. С этой целью в строке 24 командой jc анализируется флаг cf. По результату этого анализа мы уходим на ветку программы, обозначенную меткой m2, где и будут выполняться некоторые действия.

Умножение неупакованных BCD-чисел

Для того чтобы умножать числа произвольной размерности, нужно реализовать процесс умножения самостоятельно, взяв за основу некоторый алгоритм умножения, например “в столбик”.

Для того чтобы перемножить два одноразрядных BCD-числа, необходимо:

  • поместить один из сомножителей в регистр al (как того требует команда mul);
  • поместить второй операнд в регистр или память, отведя байт;
  • перемножить сомножители командой mul (результат, как и положено, будет в ax);
  • результат, конечно, получится в двоичном коде, поэтому его нужно скорректировать.

Для коррекции результата после умножения применяется специальная команда

aam (ASCII Adjust for Multiplication) — коррекция результата умножения для представления в символьном виде.

Она не имеет операндов и работает с регистром ax следующим образом:

  • делит al на 10;
  • результат деления записывается так: частное в al, остаток в ah.

В результате после выполнения команды aam в регистрах al и ah находятся правильные двоично-десятичные цифры произведения двух цифр.

В листинге 10 приведен пример умножения BCD-числа произвольной размерности на однозначное BCD-число. Данную программу можно легко модифицировать для умножения BCD-чисел произвольной длины. Для этого достаточно представить алгоритм умножения “в столбик”. Листинг 10 можно использовать для получения частичных произведений в этом алгоритме. После их сложения со сдвигом получиться искомый результат.

Перед окончанием обсуждения команды aam необходимо отметить еще один вариант ее применения. Эту команду можно применять для преобразования двоичного числа в регистре al в неупакованное BCD-число, которое будет размещено в регистре ax: старшая цифра результата в ah, младшая — в al. Понятно, что двоичное число должно быть в диапазоне 0. 99.

Деление неупакованных BCD-чисел

aad (ASCII Adjust for Division) — коррекция деления для представления в символьном виде.

Команда не имеет операндов и преобразует двузначное неупакованное BCD-число в регистре ax в двоичное число. Это двоичное число впоследствии будет играть роль делимого в операции деления. Кроме преобразования, команда aad помещает полученное двоичное число в регистр al. Делимое, естественно, будет двоичным числом из диапазона 0. 99.
Алгоритм, по которому команда aad осуществляет это преобразование, состоит в следующем:

  • умножить старшую цифру исходного BCD-числа в ax (содержимое ah) на 10;
  • выполнить сложение ah + al, результат которого (двоичное число) занести в al;
  • обнулить содержимое ah.

Далее программисту нужно выдать обычную команду деления div для выполнения деления содержимого ax на одну BCD-цифру, находящуюся в байтовом регистре или байтовой ячейке памяти.

Деление неупакованных BCD-чисел иллюстрируется листингом 11. Аналогично aam, команде aad можно найти и другое применение — использовать ее для перевода неупакованных BCD-чисел из диапазона 0. 99 в их двоичный эквивалент.

Для деления чисел большей разрядности, так же как и в случае умножения, нужно реализовывать свой алгоритм, например “в столбик”, либо найти более оптимальный путь.

Арифметические действия над упакованными BCD-числами


Сложение упакованных BCD-чисел

Видно, что как и для неупакованных BCD-чисел, для упакованных BCD-чисел существует потребность как-то корректировать результаты арифметических операций.
Микропроцессор предоставляет для этого команду daa:

daa (Decimal Adjust for Addition) — коррекция результата сложения для представления в десятичном виде.
Команда daa преобразует содержимое регистра al в две упакованные десятичные цифры по алгоритму, приведенному в описании команды daa .
Получившаяся в результате сложения единица (если результат сложения больше 99) запоминается в флаге cf, тем самым учитывается перенос в старший разряд.

Проиллюстрируем сказанное на примере сложения двух двузначных BCD-чисел в упакованном формате (листинг 12). В приведенном примере все достаточно прозрачно, единственное, на что следует обратить внимание, — это описание упакованных BCD-чисел и порядок формирования результата. Результат формируется в соответствии с основным принципом работы микропроцессоров Intel: младший байт по младшему адресу.

Вычитание упакованных BCD-чисел

При программировании вычитания упакованных BCD-чисел программист, как и при вычитании неупакованных BCD-чисел, должен сам осуществлять контроль за знаком. Это делается с помощью флага cf, который фиксирует заем из старших разрядов.
Само вычитание BCD-чисел осуществляется простой командой вычитания sub или sbb. Коррекция результата осуществляется командой das:

das (Decimal Adjust for Substraction) — коррекция результата вычитания для представления в десятичном виде.
Команда das преобразует содержимое регистра al в две упакованные десятичные цифры по алгоритму, приведенному в описании команды das .

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

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

Сложение чисел на Assembler

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

Также напомню, что мы работаем в MASM32, и соответственно, вам необходимо его установить. Как это сделать, мы рассказывали в прошлой статье по Assembler.

Как создавать файлы Assembler

Прежде чем привести вам код программы, думаю, не лишним будет написать как и где прописывать код:

1. Создать любой файл с расширением .txt

Не так важно с помощью какой программы вы это сделаете(блокнот, Notepad, и тд)

2. Пишем сам код в этом файле(пример кода будет ниже)

3. Переименовываем этот файл в файл с расширением .asm

4. Перемещаем файл в папку BIN(папка, которую использовали в 1 статье)

Код сложения чисел на Assembler

Ну и собственно небольшой код программы:

Ну что ж, вот так вот выглядит код на Assembler.
Первые 2 строчки являются обязательными для MASM, поэтому их мы будем писать в каждой программе. Они обозначают тип процессора и модель памяти с которой мы работаем.

Третья строчка — это раздел переменные( после этой строки, должны объявляться переменные), как вы видите, у нас в этой программе не будет переменных.

Четвертая — раздел кода. В нашей программе, мы помещаем в регистр eax значение 3, а затем с помощью add(прибавить) добавляем 2, логично, что теперь в этом регистре будет храниться значение 5.
Кто не знает, что такое регистр, то вам лучше почитать об этом здесь.
Затем идет команда ret, которая говорит о выходе из программы и сам выход end start.

Как запускать программы

Итак, мы имеем файл с расширением .asm, лежащий в папке BIN.
Поздравляю вас, это первый код на Assembler!
Но все же, пока не очень понятно, как нам проверить: работает ли программа(то есть скомпилировалась ли она и может ли запускаться)?
Для этого мы ее сейчас и запустим:

1. Запускаем командную строку(прописать cmd в поиске, ну или другим способом)

2. Перейти в папку BIN с помощью команды cd

У меня эта команда будет выглядеть так: cd C:UsersНикитаBIN

3. Пишем следующую запись: amake.bat имя файла(без расширения)

Я прописываю: amake.bat first

Также напомню вам, что это сработает только при правильно установленном MASM32, в предыдущей статье мы об этом говорили.

Жмем enter
Если ошибок не возникло то у вас появится что то вроде этого:

Запуск отладчика OLLYDBG

Программа скомпилировалась, а это уже хорошо, теперь нам нужно проверить как она сработала, вдруг она не сложила 2 числа.
Для этого в папке BIN открываем наш отладчик(который устанавливали в 1 статье) OLLYDBG.
В отладчике открываем файл программы (file > open first.exe), и видим наш код уже с другой стороны:

Так как мы работаем с регистром eax, то именно его значение и будем отслеживать.(в правом окне, 1 значение регистров)
Итак, чтобы пошагово прогнать нашу программу нужно нажать на 4 синию кнопку слева.(стрелка вниз с 3 точками)
После 1 нажатия, значение в eax стало равно 3, после 2 нажатия — 5.
Наша программа работает верно!

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

Сложение чисел ассемблер

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

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

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

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

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

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

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

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

Читать еще:  Что отображено на странице панель безопасности
Ссылка на основную публикацию
Adblock
detector