Справочник по языку Ассемблера IBM PC

       

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


Микропроцессор выполняет сложение операндов по правилам сложения двоичных чисел. Проблем не возникает до тех пор, пока значение результата не превышает размерности поля операнда (). Например, при сложении операндов размером в байт результат не должен превышать число 255. Если это происходит, то результат оказывается неверным. Рассмотрим, почему так происходит. К примеру, выполним сложение: 254 + 5 = 259 в двоичном виде. 11111110 + 0000101 = 1 00000011. Результат вышел за пределы восьми бит и правильное его значение укладывается в 9 бит, а в 8-битовом поле операнда осталось значение 3, что, конечно, неверно. В микропроцессоре этот исход сложения прогнозируется и предусмотрены специальные средства для фиксирования подобных ситуаций и их обработки. Так, для фиксирования ситуации выхода за разрядную сетку результата, как в данном случае, предназначен флаг переноса cf. Он располагается в бите 0 регистра флагов eflags/flags. Именно установкой этого флага фиксируется факт переноса единицы из старшего разряда операнда. Естественно, что программист должен предусматривать возможность такого исхода операции сложения и средства для корректировки. Это предполагает включение участков кода после операции сложения, в которых анализируется флаг cf. Анализ этого флага можно провести различными способами. Самый простой и доступный — использовать команду условного перехода . Эта команда в качестве операнда имеет имя метки в текущем сегменте кода. Переход на эту метку осуществляется в случае, если в результате работы предыдущей команды флаг cf установился в 1. Если теперь посмотреть на , то видно, что в системе команд микропроцессора имеются три команды двоичного сложения:

inc операнд — операция инкремента, то есть увеличения значения операнда на 1;

add операнд_1,операнд_2 — команда сложения с принципом действия: операнд_1 = операнд_1 + операнд_2

adc операнд_1,операнд_2 — команда сложения с учетом флага переноса cf. Принцип действия команды:

операнд_1 = операнд_1 + операнд_2 + значение_cf


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

Рассмотрим пример вычисления суммы чисел (листинг 3).

   Листинг 3. Вычисление суммы чисел <1>     ;prg_8_3.asm <2>     masm <3>     model   small <4>     stack   256 <5>     .data <6>     a       db      254 <7>     .code   ;сегмент кода <8>     main: <9>     mov     ax,@data <10>    mov     ds,ax <11>    ... <12>    xor     ax,ax <13>    add     al,17 <14>    add     al,a <15>    jnc     m1      ;если нет переноса, то перейти на m1 <16>    adc     ah,0    ;в ax сумма с учетом переноса <17>    m1:     ... <18>    exit: <19>    mov     ax,4c00h        ;стандартный выход <20>    int     21h <21>    end     main    ;конец программы

В листинге 3 в строках 13–14 создана ситуация, когда результат сложения выходит за границы операнда. Эта возможность учитывается строкой 15, где команда jnc (хотя можно было обойтись и без нее) проверяет состояние флага cf. Если он установлен в 1, то это признак того, что результат операции получился больше по размеру, чем размер операнда, и для его корректировки необходимо выполнить некоторые действия. В данном случае мы просто полагаем, что границы операнда расширяются до размера ax, для чего учитываем перенос в старший разряд командой adc (строка 15). Если у вас остались вопросы, исследуйте работу команд сложения без учета знака, для чего введите листинг 3, получите исполняемый модуль, запустите отладчик и откройте в нем окна View|Dump и View|Registers. 


Содержание раздела