Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#12| Old Monk & Old Hero
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Питер Абель Весь текст 992.61 Kb

Ассемблер и программирование для IBM PC

Предыдущая страница Следующая страница
1 ... 28 29 30 31 32 33 34  35 36 37 38 39 40 41 ... 85
величиной +32767. Умножение больших  чисел  требует  выполнения  некоторых
дополнительных действий.  Рассматриваемый  подход  предполагает  умножение
каждого слова  отдельно  и  сложение  полученных  результатов.  Рассмотрим
следующее умножение в десятичном формате:

                                   1365
                                    х12
                                  -----
                                   2730
                                  1365
                                  -----
                                  16380

Представим, что десятичная арифметика  может  умножать  только  двузначные
числа. Тогда можно умножить 13 и 65 на 12 раздельно, cледующим образом:

                            13             65
                           х12            х12
                           ---            ---
                            26            130
                           13             65
                           ---            ---
                           156            780

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

                                  15600
                                   +780
                                  -----
                                  16380

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

     У м н о ж е н и е   д в о й н о г о    с л о в а    н а    с л о в о.
Процедура E10XMUL на рис.12.4 умножает двойное слово на  слово.  Множимое,
MULTCND, состоит из  двух  слов,  содержащих  соответственно  шест.3206  и
шест.2521.  Определение данных в виде двух слов (DW) вместо двойного слова
(DD) обусловлено  необходимостью  правильной  адресации  для  команд  MOV,
пересылающих слова  в  регистр  AX.  Множитель MULTPLR содержит шест.6400.
Область для записи произведения,  PRODUCT,  состоит из трех  слов.  Первая
команда MUL перемножает MULTPLR и правое cлово поля MULTCND;  произведение
- шест.0E80 E400 записывается в PRODUCT+2 и PRODUCT+4.  Вторая команда MUL
перемножает MULTPLR и левое слово поля MULTCND, получая в результате шест.
138A 5800. Далее выполняется сложение двух произведений следующим образом:

               Произведение 1:     0000 0E80 E400
               Произведение 2:     138A 5800
                                   --------------
               Результат:          138A 6680 E400

     Так как первая  команда  ADD  может  выработать  перенос,  то  второе
cложение выполняется командой сложения с переносом ADC (ADd with Carry). В
силу обратного представления байтов  в  словах  в  процессоpах  8086/8088,
область PRODUCT в действительности  будет  содержать  значение  8A13  8066
00E4. Программа предполагает, что первое слово  в  области  PRODUCT  имеет
начальное значение 0000.

__________________________________________________________________________

TITLE   EXDWMUL - Умножение двойных слов
CODESG  SEGMENT PARA 'Code'
        ASSUME  CS:CODESG,DS:CODESG,SS:CODESG
        ORG     100H
BEGIN:  JMP     SHORT MAIN
; ---------------------------------------------
MULTCND DW      3206H           ;Элементы данных
        DW      2521H
MULTPLR DW      6400H
        DW      0A26H
PRODUCT DW      0
        DW      0
        DW      0
        DW      0
; ---------------------------------------------
MAIN    PROC    NEAR            ;Основная процедура
        CALL    E10XMUL         ;Вызвать 1-е умножение
        CALL    Z10ZERO         ;Очистить произведение
        CALL    F10XMUL         ;Вызвать 2-е умножение
        RET
MAIN    ENDP
;               Умножение двойного слова на слово:
; -----------------------------------------------
E10XMUL PROC
        MOV     AX,MULTCND+2    ;Умножить правое слова
        MUL     MULTPLR         ; множимого
        MOV     PRODUCT+4,AX    ;Записать произведение
        MOV     PRODUCT+2,DX

        MOV     AX,MULTCND      ;Умножить левое слово
        MUL     MULTPLR         ; множимого
        ADD     PRODUCT+2,AX    ;Сложить с полученным ранее
        ADC     PRODUCT,DX
        RET
E10XMUL ENDP
;               Перемножение двух двойных слов:
; --------------------------------------------
F10XMUL PROC
        MOV     AX,MULTCND+2    ;Слово-2 множимого
        MUL     MULTPLR+2       ; * слово-2 множителя
        MOV     PRODUCT+6,AX    ;Сохранить результат
        MOV     PRODUCT+4,DX

        MOV     AX,MULTCND+2    ;Слово-2 множимого
        MUL     MULTPLR         ; * слово-1 множителя
        ADD     PRODUCT+4,AX    ;Сложить с предыдущим
        ADC     PRODUCT+6,DX
        ADC     PRODUCT,00      ;Прибавить перенос

        MOV     AX,MULTCND      ;Слово-1 множимого
        MUL     MULTPLR+2       ; * слово-2 множителя
        ADD     PRODUCT+4,AX    ;Сложить с предыдущим
       ADC     PRODUCT+6,DX
        ADC     PRODUCT,00      ;Прибавить перенос
        MOV     AX,MULTCND      ;Слово-1 множимого
        MUL     MULTPLR         ; * слово-1 множителя
        ADD     PRODUCT+2,AX    ;Сложить с предыдущим
        ADC     PRODUCT,DX
        RET
F10XMUL ENDP
;               Очистка области результата:
; ----------------------------------------
Z10XMUL PROC
        MOV     PRODUCT,0000
        MOV     PRODUCT+2,0000
        MOV     PRODUCT+4,0000
        MOV     PRODUCT+6,0000
        RET
Z10XMUL ENDP

CODESG  ENDS
        END     BEGIN
__________________________________________________________________________

     Рис.12.4. Многословное умножение.


     У м н о ж е н и е   "д в о й н о г о  с л о в а   н а   д в о й н о е
с л о в о". Умножение двух двойных слов включает следующие четыре операции
умножения:

               Множимое       Множитель

               слово 2   х    слово 2
               слово 2   х    слово 1
               слово 1   х    слово 2
               слово 1   х    слово 1

Каждое произведение в регистрах DX и  AX  складывается  с  соответствующим
словом в окончательном результате.  Пример  такого  умножения  приведен  в
процедуре F10XMUL на рис.12.4.  Множимое MULTCND содержит шест.3206  2521,
множитель MULTPLR - шест.6400 0A26. Результат заносится в область PRODUCT,
состоящую из четырех слов.
     Хотя логика умножения  двойных  слов  аналогична  умножению  двойного
слова на слово, имеется  одна  особенность,  после  пары  команд  сложения
ADD/ADC используется еще одна команда ADC, которая прибавляет 0 к значению
в поле PRODUCT.  Это необходимо потому, что первая команда ADC сама  может
вызвать перенос, который последующие команды могут стереть. Поэтому вторая
команда ADC прибавит 0, если переноса нет,  и  прибавит  1,  если  перенос
есть. Финальная пара команд ADD/ADC не требует дополнительной команды ADC,
так как область PRODUCT достаточно  велика  для  генерации  окончательного
результата и переноса на последнем этапе не будет.
     Окончательный результат 138A 687C 8E5C CCE6 получится в поле  PRODUCT
в обратной записи байт в словах.  Выполните трассировку  этого  примера  с
помощью отладчика DEBUG.


     СДВИГ РЕГИСТРОВОЙ ПАРЫ DX:AX
     ________________________________________________________________

     Следующая подпрограмма может  быть  полезна  для  сдвига  содержимого
pегистровой пары DX:AX вправо или влево. Можно придумать более эффективный
метод, но данный пример представляет общий подход для любого числа  циклов
(и, соответственно, сдвигов) в регистре CX. Заметьте, что сдвиг единичного
бита за разрядную сетку устанавливает флаг переноса.

                     Сдвиг влево на 4 бита
               MOV  CX,04     ;Инициализация на 4 цикла
          C20: SHL  DX,1      ;Сдвинуть DX на 1 бит влево
               SHL  AX,1      ;Сдвинуть AX на 1 бит влево
               ADC  DX,00     ;Прибавить значение переноса
               LOOP C20       ;Повторить
                     Сдвиг вправо на 4 бита
               MOV  CX,04     ;Инициализация на 4 цикла
          D20: SHR  AX,1      ;Сдвинуть AX на 1 бит вправо
               SHR  DX,1      ;Сдвинуть DX на 1 бит вправо
               JNC  D30       ;Если есть перенос,
               OR   AH,10000000B  ; то вставить 1 в AH
          D30: LOOP D20       ;Повторить

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

               MOV  CL,04     ;Установить фактор сдвига
               SHL  DX,CL     ;Сдвинуть DX влево на 4 бита
               MOV  BL,AH     ;Сохранить AH в BL
               SHL  AX,CL     ;Сдвинуть AX влево на 4 бита
               SHL  BL,CL     ;Сдвинуть BL вправо на 4 бита
               OR   DL,BL     ;Записать 4 бита из BL в DL


     ДЕЛЕНИЕ
     ________________________________________________________________

     Операция деления для беззнаковых данных выполняется командой  DIV,  a
для знаковых - IDIV. Ответственность за подбор подходящей команды лежит на
программисте. Существуют две основные операции деления:

     Д е л е н и е "с л о в а  н а  б а й т". Делимое находится в регистре
AX, а делитель - в байте памяти или а однобайтовом регистре. После деления
остаток получается в регистре AH, а частное - в AL.  Так как  однобайтовое
частное очень мало (максимально +255 (шест.FF) для беззнакового деления  и
+127 (шест.7F) для  знакового),  то  данная  операция  имеет  ограниченное
использование.

                        |  AX   |           |  AH   |  AL   |
            До деления: |Делимое|    После: |Остаток|Частное|

     Д е л е н и е  "д в о й н о г о  с л о в а  н а  с л о в о".  Делимое
находится в регистровой паре DX:AX, а делитель -  в  слове  памяти  или  а
регистре.  После деления остаток получается в регистре  DX,  а  частное  в
регистре AX.  Частное в одном слове допускает максимальное значение +32767
(шест.FFFF) для беззнакового деления и +16383 (шест.7FFF) для знакового.

                   |   DX   ||   AX   |         |  AH   ||  AL   |
       До деления: |Ст.часть||Мл.часть|  После: |Остаток||Частное|
                   |     Делимое      |

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

               DIV  DIVISOR

     Если поле DIVISOR определено как байт (DB), то операция  предполагает
деление слова на байт.  Если поле DIVISOR определено как  слово  (DW),  то
операция предполагает деление двойного слова на слово.
     При делении, например, 13 на 3, получается результат 4  1/3.  Частное
есть 4, а остаток - 1. Заметим, что ручной калькулятор (или  программа  на
языке BASIC) выдает в этом случае результат  4,333....  Значение  содержит
целую часть (4) и дробную часть (,333). Значение 1/3 и 333... есть дробные
части, в то время как 1 есть остаток от деления.


                     Беззнаковое деление: Команда DIV
                    ----------------------------------
     Команда DIV делит беззнаковые числа.  На рис.12.5 в процедуре  D10DIV
дано четыре примера деления: слово на байт, байт на байт, двойное слово на
слово и слово на слово.  Первый пример команды DIV делит шест.2000  (8092)
на шест.80 (128).  В результате остаток 00 получается  в  регистре  AH,  а
частное шест.40 (64) - в регистре AL.
     Второй пример команды DIV выполняет прежде расширение байта BYTE1  до
размеров слова.  Так как здесь предполагается беззнаковая величина,  то  в
примере левый бит регистра AH равен нулю.  В результате деления остаток  -
шест.12 получается в регистре AH, а частное шест.05 - в регистре AL.
     Третий пример команды DIV генерирует остаток шест.1000 в регистре  DX
и частное шест.0080 в регистре AX.
Предыдущая страница Следующая страница
1 ... 28 29 30 31 32 33 34  35 36 37 38 39 40 41 ... 85
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (15)

Реклама