Шаг 8.
Основные арифметические команды

    На этом шаге мы познакомимся с основными арифметическими командами.

    Перечислим основные арифметические команды, используемые для организации вычислений.

Таблица 1. Основные арифметические команды
Команда
Назначение
ADD (Сложение)
Определяет двоичную сумму двух указанных операндов.
ADC (Сложение с переносом)
Определяет двоичную сумму двух указанных операндов и содержимого флага переноса CF.
INC (Инкремент)
Увеличивает содержимое операнда на 1.
SUB (Вычитание)
Определяет разность уменьшаемого и вычитаемого.
SBB (Вычитание с заемом)
Определяет разность двух операндов, и, кроме того, из уменьшаемого вычитается содержимое флага переноса.
DEC (Декремент)
Уменьшает содержимое операнда на единицу.
MUL (Умножение)
Производит беззнаковое умножение содержимого аккумулятора (регистра AL при байтовом умножении и регистра AX при умножении слов) на указанный операнд.
IMUL (Умножение целых чисел с учетом знака)
Производит умножение аккумулятора на указанный операнд с учетом знаков.
DIV (Деление)
Осуществляет деление содержимого аккумулятора (AX при байтовом делении или пары регистров DX и AX при делении слов) на указанный операнд без учета знаков.
IDIV (Деление чисел с учетом знака)
Выполняет деление содержимого аккумулятора (AX при делении байтовых чисел или пары регистров DX и AX при делении слов) на указанный операнд с учетом знаков.
MOV (Пересылка данных)
Пересылает данные из одного операнда в другой.
XCHG (Обмен значениями)
Меняет местами содержимое двух операндов.
NEG (Получение противоположного значения)
Меняет знак операнда на противоположный.

    Рассмотрим более подробно перечисленные команды.

    1. ADD (Сложение). Определяет двоичную сумму двух указанных операндов. Результат помещается на место операнда-приемника, второй операнд остается без изменения. Общий вид:

    ADD <1-й операнд>, <2-й операнд>
    <1-й операнд>  <--   <1-й операнд> + <2-й операнд>          . 

    Местом хранения первого операнда может быть регистр или ячейка памяти; второго операнда - регистр или ячейка памяти, либо он может быть задан константой. Не разрешается использовать для записи операндов сегментные регистры, а также ячейки памяти для одновременного хранения двух операндов. Операнды могут быть числами со знаком или без него и представлять собой байты или слова.


    Пример. Пусть регистр DL содержит число 58H, однобайтовая ячейка памяти TEST_BYTE содержит 27H. После выполнения команды ADD TEST_BYTE,DL в ячейку памяти будет записано 7FH:
   содержимое регистра DL:                 0101 10002 = 58H ;
   содержимое ячейки TEST_BYTE:            0010 01112 = 27H;
   новое содержимое ячейки TEST_BYTE:      0111 11112 = 7FH.

    Флаги, затрагиваемые операцией: OF, ZF, AF, PF, CF.

    К оглавлению

    2. ADC (Сложение с переносом). Определяет двоичную сумму двух указанных операндов и содержимого флага переноса CF. Результат помещается на место операнда-приемника, второй операнд остается без изменений. Общий вид:

    ADC <1-й операнд>, <2-й операнд>
    <1-й операнд>  <--   <1-й операнд> + <2-й операнд> + <CF>         . 

    Команда работает с байтами и со словами, со знаковыми и беззнаковыми двоичными числами. Первый операнд может храниться в регистре или ячейке памяти. Второй операнд может быть задан в регистре, ячейке памяти или непосредственным числовым значением. Не разрешается задавать операнды в регистрах сегментов, а также хранение (запись) двух операндов одновременно в ячейках памяти. Операнды могут быть байтами или словами, представлять числа со знаком или без знака. Поскольку команда ADC использует флаг переноса CF, то она может применяться для сложения чисел, длина которых превышает 16 бит.


    Пример 1. Пусть регистр BX содержит число 4803H, регистр AX - число 2517H, а регистр флагов процессора содержит значение F047H (11110000010001112), то есть флаг переноса CF равен 1. После выполнения команды ADC AX,BX вместо 2517H в регистре AX будет записано 6D1BH:
   содержимое BX:                 0100 1000 0000 0011 = 4803H;
   содержимое AX:                 0010 0101 0001 0111 = 2517H;
   флаг переноса CF:                                1        ;
   новое содержимое AX:           0110 1101 0001 1011 = 6D1BH.


    Пример 2. Проиллюстрируем использование этой команды при сложении так называемых "длинных" чисел, которые на помещаются в одно слово. Пусть требуется сложить два таких числа:
    224810H
    23E1ADH

Сначала сложим младшие слова этих чисел, используя команду ADD:

    4810H
    E1ADH
   ------
 (1)29BDH

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

    22H
    23H
     1H  ;Перенос от предыдущей операции.
   ------
    46H
Таким образом, окончательный результат будет следующим:
    4629BDH     .

    Флаги, затрагиваемые операцией: OF, SF, ZF, AF, PF, CF.

    К оглавлению

    3. INC (Инкремент). Увеличивает содержимое операнда на 1. Общий вид:

    INC <операнд>
    <операнд>  <--   <операнд> + 1         . 

    Операнд может быть задан в регистре общего назначения или в ячейке памяти. Сегментные регистры не могут быть использованы для хранения операндов. Команда INC может использоваться как с однобайтовыми, так и двухбайтовыми операндами. Операнды интерпретируются как числа без знака. Команда воздействует на флаги OF, SF, ZF, AF, PF.


    Пример. Пусть регистр BX задает двухбайтовую область памяти с содержимым FE00H и выполняется команда INC WORD PTR [BX]. Новым содержимым памяти после выполнения команды будет число FE01H. Так как результатом операции является отрицательное, отличное от нуля число в дополнительном коде, то флаг SF установлен в 1, а флаг ZF - в 0. Наличие только одного отличного от нуля разряда в младшем байте слова обусловливает сброс флага PF в 0.

    Замечание. Выражение [BX] сообщает Ассемблеру, что регистр BX содержит адрес операнда, а не является операндом сам по себе. Скобки [ и ], заключающие какое-либо значение, указывают Ассемблеру, что это значение - адрес. Другая часть выражения, WORD PTR, требуется Ассемблеру для информации, что операнд является переменной типа WORD (слово).


    К оглавлению

    4. SUB (Вычитание). Определяет разность уменьшаемого и вычитаемого. Результат помещается на место уменьшаемого, вычитаемое остается без изменений. Общий вид:

    SUB <1-й операнд>, <2-й операнд>
    <1-й операнд>  <--   <1-й операнд> - <2-й операнд>         . 

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


    Пример. Рассмотрим случай, когда регистр DL содержит число 58H, регистр DH - число 20H. После выполнения команды SUB DL,DH в регистре DL будет записано число 38H.

    Флаги, затрагиваемые операцией: OF, SF, ZF, AF, PF, CF.

    К оглавлению

    5. SBB (Вычитание с заемом). Определяет разность двух операндов, и, кроме того, из уменьшаемого вычитается содержимое флага переноса:

    SBB <1-й операнд>, <2-й операнд>
    <1-й операнд>  <--   <1-й операнд> - <2-й операнд> - <CF>         . 

    Результат помещается на место первого операнда, предыдущее значение которого теряется. Содержимое второго операнда не изменяется.

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


    Пример. Пусть регистр AX содержит число 4803H, регистр флагов - F047H, флаг CF установлен в 1. После выполнения команды SBB AX, 1500H в регистре AX будет записано 3302H. Флаги, затрагиваемые операцией: OF, SF, ZF, AF, PF, CF.

    К оглавлению

    6. DEC (Декремент). Уменьшает содержимое операнда на единицу:

    DEC <операнд>
    <операнд>  <--   <операнд> - 1         . 

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


    Пример. Пусть в регистре BL записано 00 и выполняется команда DEC BL. Новым содержимым регистра BL будет число FFH. Так как результат является отрицательным, отличным от нуля числом в дополнительном коде, флаг знака SF устанавливается в 1, а флаг нуля ZF сбрасывается в 0. Поскольку в результате присутствует восемь отличных от нуля битов, то есть четное число, то флаг паритета PF тоже установлен в 1.

    Флаги, затрагиваемые операцией: OF, SF, ZF, AF, PF.

    К оглавлению

    7. MUL (Умножение). Производит беззнаковое умножение содержимого аккумулятора (регистра AL при байтовом умножении и регистра AX при умножении слов) на указанный операнд. Общий вид:

    MUL <операнд>

    Если операнд является байтом, то он умножается на содержимое регистра AL и результат двойной длины (слово) записывается в регистр AX. Если операнд - слово, то он умножается на содержимое регистра AX и результат (двойное слово) записывается в пару регистров DX и AX, причем регистр DX содержит старшие разряды результата. Операнд может быть задан в регистре общего назначения или ячейке памяти и интерпретируется как число без знака. Описанный порядок выполнения команды умножения сведен в таблицу 2.

Таблица 2. Порядок выполнения команды MUL
Размер операнда
Аккумулятор
Местоположение результата
Один байт
AL
AX
Одно слово (два байта)
AX
DX:AX

    Если содержимое регистра AH после однобайтового умножения или содержимое регистра DX после двухбайтового умножения не равны нулю, флаги CF и OF устанавливаются в 1. В противном случае они сбрасываются в 0. Состояние флагов SF, ZF, AF, PF после команды MUL не определено.


    Пример 1. Пусть регистр AL содержит число 30H, однобайтовая ячейка памяти NEXT_L содержит 12H и выполняется команда MUL NEXT_L. Результат умножения (12H Х 30H = 360H) записывается в регистр AX. Поскольку содержимое регистра AH отлично от 0, флаги CF и OF установлены в 1.


    Пример 2. Пусть теперь регистр AX содержит число 1000H, регистр BX - число 550H. Тогда после выполнения команды MUL BX результат умножения (1000H Х 550H = 550000H) будет записан в пару регистров DX и AX. Так как новое значение регистра DX (0055H) отлично от нуля, то флаги CF и OF устанавливаются в 1.

    Флаги, затрагиваемые операцией: OF, SF, ZF, AF, PF, CF.

    К оглавлению

    8. IMUL (Умножение целых чисел с учетом знака). Производит умножение аккумулятора на указанный операнд с учетом знаков. Результатом байтового умножения является 16-битовое число, хранящееся в регистре AX. Результат умножения слов - 32-битовое число в паре регистров DX и AX, причем в DX - старшие 16 бит результата. Если старшая часть (AH при байтовом умножении или DX при длинах операндов, равных слову) содержит не знак младшей части результата, а его значащие цифры, флаги CF и OF переводятся в единичное состояние. В противном случае оба флага обнуляются. После выполнения IMUL состояние флагов AF, PF, SF и ZF становится неопределенным.

    Флаги, затрагиваемые операцией: OF, SF, ZF, AF, PF, CF.

    К оглавлению

    9. DIV (Деление). Осуществляет деление содержимого аккумулятора (AX при байтовом делении или пары регистров DX и AX при делении слов) на указанный операнд без учета знаков. Общий вид:

    DIV <операнд>

    Результат выполнения команды деления приведен в таблице 3.

Таблица 3. Порядок выполнения команды DIV
Размер операнда
Аккумулятор
Частное
Остаток
Один байт
AX
AL
AH
Одно слово (два байта)
DX:AX
AX
DX

    Таким образом, при 8-битовом делении целая часть отношения помещается в регистр AL, а остаток - в регистр AH. При этом, если результат деления будет больше FFH, то генерируется прерывание типа 0 (ошибка при делении).

    Для двухбайтовых операций выполняется деление содержимого регистровой пары DX:AX на указанный операнд. Если результата деления больше FFFFH, то генерируется прерывание типа 0. При 16-битовом делении целая часть отношения размещается в регистре AX, а остаток - в регистре DX.

    Операнд может быть задан в регистре общего назначения или ячейке памяти, при этом операнд рассматривается как беззнаковый 8- или 16-битовый делитель соответственно при однобайтовом и двухбайтовом делении.

    После выполнения команды DIV состояния разрядов регистра флагов процессора не определены. Если произошло переполнение, то частное и остаток не определены.


    Пример 1. Пусть регистр AX содержит число 0047H, регистр CL - число 12H и выполняется команда DIV CL. Частное от деления (03H=47H/12H) записывается в регистр AL, а остаток 11H - в регистр AH.


    Пример 2. Рассмотрим случай, когда регистры DX и AX содержат соответственно значения 0012H и F043H, представляющие 32-разрядное шестнадцатеричное число 0012F043H, регистр BP содержит число 4320H и выполняется команда DIV BP. Частное от деления (0048H=12F043H/4320H) записывается в регистр AX, а остаток (0F43H) - в регистр DX.

    Флаги, затрагиваемые операцией: OF, SF, ZF, AF, PF, CF.

    К оглавлению

    10. IDIV (Деление чисел с учетом знака). Выполняет деление содержимого аккумулятора (AX при делении байтовых чисел или пары регистров DX и AX при делении слов) на указанный операнд с учетом знаков. При 8-битовом делении отношение размещается в регистре AL, а остаток - в регистре AH. При 16-битовом делении регистр AX содержит частное, а регистр DX - остаток. При байтовом делении максимальное положительное частное не превышает 127 (7FH), а минимальное отрицательное не может быть меньше -127 (81H). При делении чисел длиной в слово максимальное положительное отношение равно 32767 (7FFFH), а минимальное отрицательное частное равно -32767 (8001H). Если отношение меньше допустимого минимума или больше максимума или если произведена попытка деления на 0, микропроцессор автоматически генерирует прерывание типа 0 (прерывание из-за ошибки деления). Отношение всегда усекается до целой части. Флаги, затрагиваемые операцией: OF, SF, ZF, AF, PF, CF.

    К оглавлению

    11. Для написания простейших программ на языке Ассемблера необходима еще одна команда, непосредственно не относящаяся с арифметическим командам. Это команда MOV (Пересылка данных):

    MOV <1-й операнд>, <2-й операнд>
    <1-й операнд>  <--   <2-й операнд>         . 

    Второй операнд при выполнении команды MOV занимает место хранения первого операнда. При этом первый операнд теряется.

    Первый операнд может быть задан в регистре общего назначения, регистре сегмента (кроме регистра CS) или ячейки памяти. Второй операнд, кроме того, может быть еще и константой. Команда MOV работает как с однобайтовыми, так и с двухбайтовыми словами.


    Пример. Пусть регистр CX содержит слово 04C5H, а регистр BP - слово 2312H. После выполнения команды MOV CX,BP содержимым регистра CX будет слово 2312H, а содержимое регистра BP не изменится.

    К оглавлению

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

    XCHG <1-й операнд>, <2-й операнд>
    <1-й операнд>  <-->   <2-й операнд>         . 

    К оглавлению

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

    NEG  <операнд>         . 


    Пример. Пусть регистр AX содержит слово 0001H. После выполнения команды NEG AX содержимым регистра AX будет FFFFH. Таким образом, команда NEG инвертирует значения битов и прибавляет 1.

    К оглавлению

    На следующем шаге мы рассмотрим основные логические команды.


Предыдущий шаг Содержание Следующий шаг