Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Команды DIV и IDIV 1 страница




Команды MUL и IMUL

Команда MUL может быть записана в трех различных форматах — в зависимости от операнда:

MUL r/m8 MUL r/ml6 MUL r/m32

В 8-разрядной форме операнд может быть любым 8-битным регистром или адресом памяти. Второй операнд всегда хранится в AL. Результат (произведение) будет записан в регистр АХ.

(r/m8)*AL -> АХ

В 16-разрядной форме операнд может быть любым 16-битным регистром или адресом памяти. Второй операнд всегда хранится в АХ. Результат сохраняется в паре DX:AX.

(r/ml6)*АХ -> DX:AX

В 32-разрядной форме второй операнд находится в регистре ЕАХ, а результат записывается в пару EDX.EAX.

(r/m32)*ЕАХ -> EDX:ЕАХ

Пример 1: умножить значения, сохраненные в регистрах ВН и CL, результат сохранить в регистр АХ:

mov al,bh; AL = ВН — сначала заносим в AL второй операнд

mul cl; АХ = AL*CL — умножаем его на CL

Результат будет сохранен в регистре АХ.

Пример: вычислить 4862, результат сохранить в DX:AX:

mov ax,486; АХ = 486

mul ах; АХ*АХ —> DX:AX

Пример 2: вычислить диаметр по радиусу, сохраненному в 8-битной переменной radius l, результат записать в 16-битную переменную diameterl:

mov al,2; AL = 2

mul byte [radiusl]; AX = radius * 2

mov [diameterl],ax; diameter <— AX

Почему результат 16-разрядного умножения сохранен в паре DX:AX, а не в каком-то 32-разрядном регистре? Причина — совместимость с предыдущими 16-разрядными процессорами, у которых не было 32-разрядных регистров.

 

Команда IMUL умножает целые числа со знаком и может использовать один, два или три операнда. Когда указан один операнд, то поведение IMUL будет таким же, как и команды MUL, просто она будет работать с числами со знаком.

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

imul edx,ecx; EDX = EDX*ECX

imul ebx,[sthing]; умножает 32-разрядную

; переменную "sthing" на ЕВХ,

; результат будет сохранен в ЕВХ

imul есх,6; ЕСХ = ЕСХ*6

Если указано три операнда, то команда IMUL перемножит второй и третий операнды, а результат сохранит в первый операнд. Первый операнд — только регистр, второй может быть любого типа, а третий должен быть только непосредственным значением:

imul edx,ecx,7; EDX = ECX*7

imul ebx,[sthing],9; умножаем переменную "sthing" на 9,

; результат будет сохранен EBX

imul ecx,edx,ll; ЕСХ = EDX*11

Подобно команде MUL, команда DIV может быть представлена в трех различных форматах в зависимости от типа операнда (операнд служит делителем, а делимое находится в фиксированном месте):

DIV r/m8 DIV r/ml6 DIV r/m32

В 8-битной форме переменный операнд (делитель) может быть любым 8-битным регистром или адресом памяти. Делимое содержится в АХ. Результат сохраняется так: частное — в AL, остаток — в АН.

АХ/(r/m8) —> AL, остаток —> АН

В 16-битной форме операнд может быть любым 16-битным регистром или адресом памяти. Второй операнд всегда находится в паре DX:AX. Результат сохраняется в паре DX:AX (DX — остаток, АХ — частное).

DX:AX/(r/ml6) —> АХ, остаток —> DX

В 32-разрядной форме делимое находится в паре EDX:EAX, а результат записывается в пару EDX:EAX (частное в ЕАХ, остаток в EDX).

EDX:EAX/(r/m32) —> ЕАХ, остаток —> EDX

Команда IDIV используется для деления чисел со знаком, синтаксис ее такой же, как у команды DIV.

Пример 1: разделить 13 на 2, частное сохранить в BL, а остаток в — ВН:

mov ах,13; АХ = 13

mov cl,2; CL = 2

div cl; делим на CL

mov bx,ax; ожидаемый результат находится

; в АХ, копируем в ВХ

Пример 2: вычислить радиус по диаметру, значение которого сохранено в 16-битной переменной diameter1, результат записать в radius1, а остаток проигнорировать.

mov ax,[diameter1]; AX = diameter1

mov bl,2; загружаем делитель 2

div bl; делим

mov [radiusl],al; сохраняем результат

 

 

Лекция 12. Особенности обработки целых чисел

в языке Ассемблера

12.1. Форматы целых чисел

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

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

Остановимся на особенностях манипуляций знаковыми и беззнаковыми числами. Аппаратная интерпретация процессором старшего бита операнда реализована в командах IMUL и IDIV. Команды ADD и SUB не делают разницы между знаковыми и беззнаковыми величинами, они просто складывают и вычитают биты, поэтому в этих случаях забота о правильной трактовке старшего бита ложится на программное обеспечение. Хочу особо подчеркнуть, что процессор ничего не предполагает относительно знака числа и выполняет вычисления двоичных значений. При этом фиксируется ситуация выхода за пределы разрядной сетки операнда (флаг CF) и состояние старшего разряда (флаг OF).

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

12.2. Сложение и вычитание целых чисел

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

При выполнении операций сложения/вычитания, как и для других арифметических операций, для получения правильного результата необходимо контролировать состояние некоторых флагов процессора. Это касается флагов CF и OF. С помощью этих флагов программа должна учитывать возможное переполнение результата и перенос в старшие разряды. Для этого отслеживаются условия, задаваемые флагами, и выполняются действия:

• CF = OF = 0 – результат правильный и является положительным числом;

• CF = 1, OF = 0 – результат правильный и является отрицательным числом;

• CF = OF = 1 – результат неправильный и является положительным числом, хотя правильный результат должен быть отрицательным (для корректи­ровки необходимо увеличить размер результата в два раза и заполнить это расширение нулевым значением);

• CF = 0, OF = 1 – результат неправильный и является отрицательным числом, хотя правильный результат должен быть положительным (для корректировки необходимо увеличить размер результата в два раза и произвести расширение знака).

Выполнение арифметических операций иногда может приводить к ситуации переполнения. Рассмотрим, например, операцию сложения для знаковых операндов размерностью в 1 байт. Один байт содержит знаковый бит и 7 бит данных, то есть диапазон допустимых значений находится между -128 и +127. Не исключена возможность, что результат арифметической операции может легко превзойти емкость однобайтового регистра.

Необходимо учитывать и то, что результат сложения в регистре AL, превышающий его емкость, автоматически не переходит в регистр АН. Предположим, что регистр AL содержит 60h, тогда после выполнения следующей команды в AL будет находиться значение 80h:

add AL, 20h

Кроме того, устанавливаются флаг переполнения и знаковый флаг. Причина заключается в том, что шестнадцатеричное значение 80 (двоичное 1000 0000) является отрицательным числом. Таким образом, вместо +128 мы получаем -128. Очевидно, что размерность регистра AL недостаточна для такой операции, поэтому можно использовать регистр АХ. Увеличить размерность операнда можно с помощью команды CBW (Convert Byte to Word — преобразовать байт в слово).

В следующем примере значение 60h в регистре AL преобразуется в шестнадцатеричное значение 60 в регистре АХ. Знаковый бит передается в регистре АН. В этом случае команда ADD дает правильный результат и в регистре АХ будет находиться значение, равное шестнадцатеричному значению 0080h или в десятичной нотации +128:

cbw; расширить AL до АХ

add АХ, 20h; прибавить 20Н к АХ

Следует заметить, что полное 16-разрядное слово имеет также ограничение: один знаковый бит и 15 бит данных, что соответствует значениям от -32768 до +32767.

Лучше всего анализировать эти операции на практических примерах. В первом примере выполняется сложение двоичных чисел размером в 1 байт без учета знака. Программный код реализован в виде процедуры addb_unsigned и показан в листинге 12.1.

Листинг 12.1. Сложение однобайтовых чисел без знака

В этом примере результат сложения сохраняется в переменной sum, а возможное переполнение из-за недостаточной размерности операндов фиксируется в переменной carry. Таким образом, программа учитывает возможное переполнение результата. Например, если op1 содержит значение 140, а ор2 – 119, то после сложения в переменной sum будет содержаться значение 3, а переменная carry получит значение 1. Это легко объяснимо, поскольку произошло переполнение регистра AL – результат превысил значение 256.

При вычитании однобайтовых чисел вместо команды ADD применяется команда SUB. Кроме того, операция вычитания может дать отрицательное число, и это необходимо учитывать для правильной интерпретации результата. В следующем примере выполняется вычитание двоичных чисел размером в 1 байт. Программный код реализован в виде процедуры sub_bytes (листинг 12.2).

По сравнению с предыдущим примером здесь все команды сложения заменены аналогичными командами вычитания. Для значений op1 и ор2, равных, например, 119 и 140 соответственно, после операции вычитания переменная substract будет содержать шестнадцатеричное значение ЕВh. Это значение можно рассматривать и как беззнаковое число 235, и как отрицательное -21. По смыслу задачи разность opl и ор2 должна быть равной -21. Из этого примера видно, что интерпретация результата арифметической операции возлагается на программиста.

Листинг 12.2. Вычитание однобайтовых чисел

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

Вернемся к первому примеру (листинг 12.1). Видно, что сохраненное в переменной sum значение равно 3, в то время как правильный результат должен быть 259. Для того чтобы получить реальное значение sum, необходимо сделать некоторые изменения в программе. Модифицированный вариант программы показан в листинге 12.3.

Проанализируем внесенные изменения. Во-первых, переменная sum имеет теперь разрядность слова, что позволяет расширить диапазон сохраняемых значений до 65536. Во-вторых, при возникновении переноса он учитывается в старшем байте регистра АХ (команда ADC AH, 0). Наконец, сам результат имеет разрядность 16 бит, что в данном случае дает правильный результат – переменная sum будет содержать значение 259.

Листинг 12.3. Модифицированный вариант сложения однобайтовых чисел

Сложение двоичных чисел большей размерности (2-4 байта) выполняется аналогично. Для этого необходимо заменить директиву DB на DW/DD и регистр AL на АХ/ЕАХ. Следующий пример демонстрирует это (листинг 12.4).

Листинг 12.4. Сложение двух чисел размером в слово

Результатом сложения двух слов, op1 и ор2, является число 10526. Операцию сложения двух слов выполняет процедура addw_unsigned. В большинстве современных программных продуктов приходится иметь дело с большими числами, представленными несколькими байтами. Например, для сложения многобайтовых чисел без знака требуется более сложный алгоритм, чем для байтов или слов. Чтобы понять принцип нахождения суммы многобайтовых чисел без знака, рассмотрим пример сложения двухбайтовых чисел и расширим наш алгоритм для случая произвольного числа байтов. Следующая процедура (назовем ее add_multibytes) складывает два двухбайтовых числа (листинг 12.5).

Листинг 12.5. Сложение двух двухбайтовых чисел

Нахождение суммы операндов opl и ор2 выполняется по такой схеме: вначале находим сумму младших байтов этих операндов и заносим ее в младший байт переменной sum, которая будет содержать результат сложения. После этого находим сумму старших байтов переменных opl и ор2 и помещаем ее в старший байт переменной sum, при этом учитывается флаг переноса (вместо команды ADD применяется ADC). Следует заметить, что размерность операндов opl и ор2 должна быть одинаковой. Изменим программный код процедуры add_multibytes (листинг 12.5) так, как показано в листинге 12.6.

Модифицированная процедура работает точно так же, как исходная, основное различие в том, что вычисление частичных сумм одинаковых байтов выполняется в цикле. При этом в счетчике СХ содержится размер операндов в байтах. Эту процедуру можно использовать для суммирования большего числа байтов, если изменить значение в счетчике СХ. Для заданных значений операндов op1 и ор2 результат равен 17499.

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

 


Листинг 12.6. Сложение двух двухбайтовых чисел (версия 2)

Листинг 12.7. Вычитание двухбайтовых чисел

Для данных значений операндов результат вычитания равен 3697.

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

Листинг 12.8. Сложение 8-байтовых чисел (32-разрядная версия)

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

Ввиду наличия цикла используется только одна команда сложения ADC. Перед выполнением цикла команда CLC устанавливает нулевое значение флага переноса CF. Для того чтобы подобный алгоритм работал, необходимо обеспечить смежность слов, выполняя обработку справа налево. Кроме того, дополнительно установите счетчик байтов в регистре ЕСХ.

Результатом выполнения программного кода при данных значениях операндов является число 107590, помещенное в переменную sum. Эту процедуру можно использовать при разработке программы на одном из языков высокого уровня. Наиболее удобный способ сделать это – поместить 32-разрядный адрес переменной sum в регистр ЕАХ и вернуть управление основной программе.

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

После выполнения этого фрагмента программного кода переменная op_word, имеющая размерность слова, в старшем байте будет содержать нули, а в младшем – значение 5.

Если необходимо преобразовать знаковое число, требуется более сложная процедура. Для решения подобных задач в процессор Intel Pentium включен ряд специальных команд, облегчающих процесс преобразования:

• CBW (Convert Byte to Word – преобразование байта в слово) – команда заполняет регистр АН знаковым битом числа, находящегося в регистре AL, что дает возможность выполнять арифметические операции над исходным операндом-байтом, как над словом в регистре АХ. Команда не имеет параметров и не воздействует на флаги процессора;

• CWD (Convert Word to Double – преобразование слова в двойное слово) – команда преобразует слово в регистре АХ в двойное слово в регистрах DX:АХ, при этом старший бит в регистре АХ распространяется на все биты регистра DX;

• CDQ (Convert Double Word to Quarter Word – преобразование двойного слова в учетверенное) – двойное слово, находящееся в регистре ЕАХ, преобразуется в учетверенное слово в регистрах EDX:ЕАХ, при этом старший бит регистра ЕАХ распространяется на все биты регистра EDX.

Команда CDQ расширяет знак двойного слова в регистре ЕАХ на регистр EDX. Эту команду можно использовать для образования четырехсловного делимого из двухсловного перед операцией двухсловного деления. Команда не имеет параметров и не воздействует на флаги процессора.

Для демонстрации работы команд преобразования типов рассмотрим пример, в котором вычитаются многобайтовые числа разного размера. Сама операция реализуется в процедуре _sub_8bytes (листинг 12.9).

Процедура _sub_8bytes посредством регистра ЕАХ возвращает адрес переменной substract, содержащей результат вычитания.

Листинг 12.9. Вычитание многобайтовых чисел разного размера (32-разрядная версия)

12.3. Умножение и деление целых чисел

Операция умножения для беззнаковых данных выполняется с помощью команды MUL, а для знаковых – IMUL (Integer Multiplication – умножение целых чисел). Формат обрабатываемых чисел и выбор подходящей команды умножения определяет сам программист. Существует несколько форматов для команд умножения:

• Множимое находится в регистре AL, а множитель – в ячейке памяти размером в 1 байт или в однобайтовом регистре. После умножения результат помещается в регистр АХ. Операция перезаписывает данные в регистре АН.

• Множимое находится в регистре АХ, а множитель – в однословной ячейке памяти или в регистре. Произведение представляет собой двойное слово, старшая часть которого размещается в регистре DX, а младшая — в регистре АХ. Операция перезаписывает данные, которые до этого находились в регистре DХ.

• Множимое находится в регистре ЕАХ, а множитель – в двухсловной ячейке памяти или в регистре. Произведение представляет собой два двойных слова, при этом старшее слово размещается в регистре EDX, а младшее — в регистре ЕАХ. Операция перезаписывает данные, которые до этого находились в регистре ЕDХ.

Команды MUL и IMUL имеют единственный операнд, являющийся множителем. Проанализируем следующую команду:

mul орr

Здесь множителем является переменная орr. Если переменная орr определена как байт, то операция предполагает умножение содержимого AL на значение байта в переменной орr. Если переменная определена как слово, то операция предполагает умножение содержимого АХ на значение слова, содержащегося в орг. Наконец, если переменная орr определена как двойное слово, то операция предполагает умножение содержимого ЕАХ на значение двойного слова в переменной орr.

Если множитель находится в регистре, то размерность регистра определяет тип операции, например:

mul CL

Поскольку регистр CL содержит один байт, то в качестве множимого будет выбран регистр AL, а произведение помещается в регистр АХ. Если выполняется следующая команда, то множитель в регистре ВХ имеет размерность слова, поэтому в качестве множимого выбирается регистр АХ, при этом произведение помещается в пару регистров DX:АХ:

mul ВХ

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

Для расширения размерности операнда можно использовать команду MOVZX (Move with Zero-Extend — копирование с расширением нуля) либо команду MOVSX (Move with Sign Extend — копирование с расширением знака):

movzx AХ, op_byte

movsx AХ, op_byte

movzx EAХ, AX

Первая команда MOVSX помещает 8-байтовый операнд в 16-разрядный регистр АХ, расширяя знак на старшую половину АХ (регистр АН). Вторая команда movsx преобразует 16-разрядное значение в 32-разрядное и помещает его в регистр ЕАХ. Команда MOVZX применяется только для беззнаковых операндов или в случаях, когда знак операнда не имеет значения.

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

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

В этом случае операция умножения может выполняться для операндов размером в байт или слово. Максимальное знаковое значение слова не может превышать +32767, поэтому умножение больших чисел требует некоторых дополнительных операций. Один из простых вариантов умножения больших чисел предполагает попарное умножение отдельных слов и сложение полученных результатов. Алгоритм этой процедуры напоминает умножение столбиком при нахождении произведения десятичных чисел.

Эффективность операций умножения можно повысить, если использовать несколько простых приемов. Например, при умножении на степень числа 2 (2, 4, 8 и т. д.) эффективнее вместо умножения выполнять логический сдвиг влево на требуемое число битов. Сдвиг более чем на 1 требует загрузки величины сдвига в регистр CL.

Рассмотрим, как выполняется операция деления в процессорах Intel. Для деления беззнаковых данных используется команда DIV, а для знаковых – IDIV. Какую из этих команд выбрать, решает разработчик программы. В зависимости от размерности операндов существуют следующие форматы операции деления:

Деление слова на байт. Делимое находится в регистре АХ, а делитель – в байте памяти или в однобайтовом регистре. После деления остаток помещается в регистр АН, а частное – в AL. Операция с данными типами операндов имеет ограниченное применение из-за небольшого диапазона допустимых значений (однобайтовое частное не превышает +255 для беззнакового деления и +127 – для знакового).

Деление двойного слова на слово. Делимое находится в регистровой паре DX:АХ, а делитель – в слове памяти или в регистре. После деления остаток помещается в регистр DX, а частное – в регистр АХ. Частное в одном слове допускает максимальное значение +65535 для беззнакового деления и +32767 – для знакового.

Деление учетверенного слова на двойное слово. Делимое находится в регистровой паре EDX:ЕАХ, а делитель – в двойном слове памяти или в регистре. После деления остаток помещается в регистр EDX, а частное – в регистр ЕАХ.

Команды DIV и IDIV имеют единственный операнд, являющийся делителем. Рассмотрим следующую команду:

div DIVISOR

Если переменная divisor определена как байт, то предполагается деление слова на байт. Если переменная divisor определена как слово (DW), то операция предполагает деление двойного слова на слово. При делении, например, 13 на 3 получается результат 4 1/3. Частное будет равным 4, а остаток – 1. Флаги состояния CF, OF, SF и ZF после выполнения команд DIV и IDIV не определены.

Если делимое и делитель имеют одинаковый знаковый бит, то команды DIV и IDIV генерируют одинаковый результат. Но если делимое и делитель имеют разные знаковые биты, то команда DIV генерирует положительное частное, а команда IDIV – отрицательное частное.

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

При использовании команд DIV и IDIV может возникнуть переполнение, что вызывает прерывание. Подобная ситуация может случиться при делении на ноль, а также не исключается при делении на 1.

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

Команда NEG обеспечивает преобразование знака двоичных чисел из плюса в минус и наоборот. Эта особенность может быть использована при нахождении абсолютной величины (модуля) числа. В практическом плане команда NEG устанавливает противоположные значения битов и прибавляет 1.

neg AX

neg BL

Преобразование знака для 32-разрядного (или большего) числа требует дополнительных шагов. В качестве примера рассмотрим преобразование знака для 32-разрядного числа, находящегося в регистрах DX:АХ. Поскольку команда NEGне может обрабатывать два регистра одновременно, то ее непосредственное применение приведет к неправильному результату. Для правильного преобразования необходимо выполнить такую последовательность команд:

12.4. Работа с числами в форматах ASCII и BCD

Для получения высокой производительности компьютер выполняет арифметические операции над числами в двоичном формате. Во многих случаях новые данные вводятся программой с клавиатуры в виде ASCII-символов в десятичном формате. Аналогично, вывод информации на экран осуществляется в ASCII-кодах. Например, число 23 в двоичном представлении выглядит как 00010111, а в шестнадцатеричном – как 17h. В ASCII-коде на каждый символ требуется один байт, поэтому число 25, например, в ASCII-коде имеет внутреннее представление 3235h.

Преобразование ASCII-чисел в двоичный формат




Поделиться с друзьями:


Дата добавления: 2014-12-07; Просмотров: 4418; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.085 сек.