Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

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




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

Инструкции MUL используется для умножения беззнаковых величин, а инструкция IMUL – для умножения знаковых чисел. Обе инструкции могут изменять состояние флагов переноса CF и переполнения OF. На программиста возлагается задание формата данных, подлежащих обработке, и выбор подходящей инструкции умножения.

Формат инструкций следующий:

MUL регистр

MUL память

IMUL регистр

IMUL память.

Можно умножать байт на байт, слово на слово и в 32-разрядных моделях Intel – двойное слово на двойное слово.

Как видно из формата, в команде указывается только один из сомножителей, второй сомножитель по умолчанию располагается в регистре AL для байтовых операндов и в регистре АХ – для двухбайтовых операндов.

Для операции умножения правило операндов описано таблицей:

Сомножитель_1 Сомножитель_2 Результат
Байт (в РОН или ячейке памяти) AL 16 бит в АХ: в AL – младшая часть результата, в AH - старшая
Слово (в РОН или ячейке памяти) АХ 32 бита в паре DX: AX; в AX – младшая часть результата, в DX – старшая часть результата

 

 

Примеры команды MUL:

BYTE1 DB 80H

BYTE2 DB 40H

WORD1     DW 8000H

WORD2     DW 2000H

MOV AL, BYTE1    ; байт умножается на байт

MUL BYTE2          ; результат в АХ, равный 2000Н (8192=128*64)

(если до команды MOV AL, BYTE1 в АН содержались какие-либо данные, командой MUL BYTE2 эти данные будут затерты)

MOV AX, WORD1  ; слово умножается на слово

MUL WORD2        ; результат в в DX: AX, равный 1000 0000Н

Как видно из таблицы, операнды-сомножители должны иметь одинаковый формат: либо оба операнда – байты, либо оба операнда – слова. Если потребуется умножить байт на слово, необходимо сначала привести в соответствие размеры операндов. В Ассемблере существуют команды CBW –преобразовать байт в слово и CWD – преобразовать слово в двойное слово. Обе команды не имеют операндов. Команда CBW по умолчанию оперирует содержимым регистра AL, а результат помещает в регистр AX. Команда CWD по умолчанию выбирает слово из регистра AX и помещает результат в DX: AX. Преобразование заключается в заполнении битом знакового разряда старших регистров результата – для команды CBW – регистра АН, а для команды CWD – регистра DX.

СBW – преобразовать байт в регистре AL в слово в регистре АХ путем распространения старшего бита AL на все биты регистра AH;

CWD –преобразовать слово в регистре АХ в двойное слово в регистрах AX и DX, путем распространения старшего 15-ого бита регистра АХ на все биты регистра DX. Эти команды позволяют приводить разноформатные операнды к одному формату (большему).

Обе команды дают верный результат при работе со знаковыми данными, но могут давать ошибочные результат с беззнаковыми данными. Например,

 MOV AL, BYTE2

CBW

позволит получить результат в АХ, равный 0020Н, а команды

MOV AL, BYTE1

CBW

даст результат в АХ, равный FF80H, что, конечно, неверно.

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

MOV AL, BYTE1

MOV AH, 0                      ; поместили сомножитель в регистр АХ

MUL WORD2        ; результат в в DX: AX, равный 1 0000Н

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

MOV AL, BYTE1    ; байт умножается на байт

IMUL BYTE2          ; результат в АХ, равный E000Н (-8192=-128*64)

MOV AX, WORD1  ; слово умножается на слово

MUL WORD2        ; результат в в DX: AX, равный F0000000Н

MOV AL, BYTE1

CBW                           ; поместили сомножитель в регистр АХ (FF80H)

IMUL WORD1        ; результат в в DX: AX, равный 0040 0000Н.

 

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

Результат перемножения правильных неупакованных BCD-чисел может быть представлен в неупакованном формате BCD-чисел с помощью команды ААМ. Команда работает с регистрами AL и AH и выполняет следующее: делит значение регистра AL на 10 и запоминает частное в регистре АН (старшая неупакованная цифра результата) и остаток – регистре AL (младшая неупакованная цифра результата). Однако очевидно, что этими операциями можно выполнить только табличное умножение. Для более сложных операций умножения необходимо разработать программу, реализующую умножение “в столбик”, получение частных произведений, их сдвиги и сложение. Операции, аналогичной ААМ для упакованных BCD-чисел в микропроцессоре не существует.

В операции деления также, как и при умножении учитывается знак: операция DIV обрабатывает беззнаковые числа, а опtрация IDIV – знаковые. Подходящую команду в каждом конкретном случае выбирает программист.

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

Формат инструкций следующий:

DIV регистр

DIV память

IDIV регистр

IDIV память.

Как видно из формата, в команде указывается только делитель, делимое по умолчанию располагается в регистре AХ или в паре регистров DX: АХ.

Для деления правило расположения операндов отражается в таблице:

Делимое Делитель Частное Остаток
Слово 16 бит в регистре АХ Байт (в РОН или ячейке памяти) Байт в регистре AL Байт в регистре AH
32 бита в DX –старшая часть, в АХ- младшая Слово 16 бит (в РОН или ячейке памяти) Слово 16 бит в регистре АХ Слово 16 бит в регистре DX

 

Примеры команды DIV:

BYTE1 DB 80H

BYTE2 DB 16H

WORD1     DW 2000H

WORD2     DW 0010H

WORD3     DW 1000H

MOV AX, WORD1  ; делимое -> в АХ

DIV BYTE1          ; получим частное вAL, остаток – AH

; в AL – значение 40Н (8192: 128=64-частное и 0 –остаток), в АН –00Н

Интерпретируем значение в BYTE1 как беззнаковое и разделим его на значение из BYTE2.

MOV     AH, 0              ; подготавливаем старшую часть делимого

MOV     AL, BYTE1            ; заполняем младшую часть делимого

DIV BYTE2          ; делим слово на байт, в AL 05Н, в AH – 12Н

При делении может возникать прерывание ”деление на 0”. Такой результат может получиться не только, когда делитель равен 0, но и в следующих случаях:

1) при делении чисел без знака для ситуации первой строки таблицы делимое более чем в 256 раз больше делителя,

2) при делении чисел без знака для ситуации второй строки таблицы делимое более чем в 65636 раз больше делителя,

3) при делении чисел со знаком для ситуации первой строки таблицы делимое более чем в 128 раз больше значения делителя,

4) при делении чисел со знаком для ситуации второй строки таблицы делимое более чем в 32768 раз больше значения делителя.

Приведу некоторые полезные приемы программирования.

Если частное слишком велико, можно выполнить деление с помощью последовательного вычитания делителя из делимого, например, делимое представляет слово, а делитель – байт, однако результат деления превышает байт (численные значения могут быть такими: делимое-64000, делитель – 80, результат деления 800 превышает максимальное значение, хранимое в одном байте). Фрагмент программы при условии, что делимое находится в регистре АХ, а делитель – в регистре ВХ, может быть следующим:

 SUB CX, CX          ; очистка регистра частного

L20: CMP AX, BX ; если делимое меньше делителя

       JB L30       ; вычитания закончить

SUB AX, BX ; вычесть делитель из делимого

INC CX       ; увеличить частное на 1

JMP L20       ; идти на начало цикла вычитания

L30:    . . . . . . . .

При попадании в точку L30 СХ содержит частное, АХ – остаток.

Если делимое – двойное слово в паре DX: AX, то

    SUB CX, CX          ; очистка регистра частного

L20: CMP DX, 0    ; пока DX не 0 – делимое больше делителя

       JNE L30

       CMP AX, BX ; если делимое меньше делителя

       JB L40       ; вычитания закончить

L30:     SUB AX, BX ; вычесть делитель из делимого

       SBB DX, 0    ; учесть возможный заем

; SUB AX, BX ; вычесть делитель из делимого

INC CX       ; увеличить частное на 1

JMP L20       ; идти на начало цикла вычитания

L40:    . . . . . . . .

Большое делимое и малый делитель вызовут многократное повторение команд!

Если необходимо разделить число на степени числа 2, то можно деление заменить сдвигами, например требуется разделить двойное слово в паре DX: AX на 16:

SHR             AX, 04  ; делим младшую часть делимого

MOV  BL, DL           ; сохраняем 3-ий байт в BL

SHR    DX, 04            ; делим старшую часть делимого

SHL    BL, 04                      ; умножаем 3-ий байт на 16, поскольку младший полубайт старшего слова должен перейти в старший полубайт младшего слова результата

OR AH, BL            добавляем полубайт к 3-ему байту результата

Для вышеприведенного фрагмента можно дать следующую наглядную интерпретацию(см. рисунок 9. 1). Первая позиция рисунка отображает исходное значение двойного слова, каждая следующая позиция отражает результат выполнения команды программы. Не отражаемые в очередной позиции байты регистров не изменяются, т. е. остаются такими же, как и в предыдущей позиции. В правильности результата легко убедиться, если сдвинуть на 4 разряда вправо каждый разряд исходного кода.

 

                       DX                                             AX

 


1 1 1 0 1 0 1 1
1 0 1 1 0 1 0 1
1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1
                                                                                                                         

0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1
0 0 0 0 1 0 1 1
0 1 0 1 1 1 1 0

 


        DL                             BL

1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
0 0 0 0 0 1 0 1
0 1 0 1 1 1 1 1

 

 


                              DX

                                                                            BL

1 1 1 1 0 0 0 0
0 1 0 1 1 1 1 1
1 1 1 1 1 0 1 1
0 1 0 1 1 1 1 0
0 0 0 0 0 1 0 1

 

 


                        DX                                                      AX

 

Рисунок 9. 1. Наглядная интерпретация фрагмента программы деления двойного слова на 16

 

Процесс выполнения деления 2 неупакованных BCD-чисел может быть представлен в формате неупакованных BCD-чисел. Для этого перед операцией деления в регистре АХ получают 2 неупакованные цифры делимого (выполняет эту операцию программист удобным для него способом). Далее командой AAD преобразуется число в двоичное, которое затем является делимым в операции DIV. Причем в дальнейшей операции DIV двоичное число делится на неупакованную BCD-цифру, находящуюся в байтовом регистре или в байтовой ячейке памяти. Результат операции получается так, как описано 1-ой строкой таблицы. Понятно, что с применением этих команд можно выполнять очень простые операции деления, но команду AAD можно использовать и в контексте преобразования упакованного (или неупакованного) десятичного числа из диапазона 00-99 в двоичный эквивалент.

К группе арифметических команд относят команды расширения операнда, которые называются командами преобразования:

Рассмотрев арифметические операции можно сделать следующие выводы:

1) рассмотренная нами группа команд выполняет известные арифметические операции над целыми числами, для работы с вещественными числами применяют команды сопроцессора;

2) многие команды имеют только один операнд или не имеют операндов вообще, поскольку по умолчанию работают с определенными регистрами общего назначения;

3) арифметические операции чувствительны к размерности операндов, поэтому эту характеристику необходимо отслеживать программисту;

4) контроль за правильностью арифметических операций полностью лежит на программисте; программист должен отслеживать состояние арифметических флагов во время вычислительного процесса и принимать правильные решения по дальнейшей обработке;

5) для чисел со знаком установка в 1 флага OF говорит о том, что в результате сложения чисел одного знака результат выходит за границу допустимых значений чисел со знаком в данном формате и сам результат меняет знак (имеет другой знак, чем его операнды).

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...