Иллюстрированный самоучитель по задачам и примерам Assembler
Прежде чем программировать, запишите программу в псевдокодах.
Д. Ван Тассел
Сложение чисел размером 1 байт без учета знака
Программа учитывает возможное переполнение результата. Сложение двоичных чисел большей размерности (2/4 байта) выполняется аналогично. Для этого необходимо заменить директивы DB на DW/DD и регистр AL на АХ/ЕАХ.
Сложение чисел размером N байт без учета знака
Программа учитывает возможное переполнение результата. Сегмент данных может быть задан, например, так:
Далее при рассмотрении программы деления многобайтных двоичных чисел нам понадобится макрокоманда сложения без учета знака чисел размером N байт (порядок следования байтов не соответствует порядку следования байтов на процессорах Intel, то есть старший байт находится по младшему адресу). Приведем ее.
Как сложить 2 двоичных числа в ассемблере
7.1. Сложение и вычитание.
7.1.1. ADD – команда для сложения двух чисел. Она работает как с числами со знаком, так и без знака.
ADD Приемник , Источник
Логика работы команды:
<Приемник> = <Приемник> + <Источник>
Возможные сочетания операндов для этой команды аналогичны команде MOV .
По сути дела, это – команда сложения с присвоением, аналогичная принятой в языке C / C ++:
Приемник += Источник;
Операнды должны иметь одинаковый размер. Результат помещается на место первого операнда.
После выполнения команды изменяются флаги, по которым можно определить характеристики результата:
- Флаг CF устанавливается, если при сложении произошёл перенос из старшего разряда. Для беззнаковых чисел это будет означать, что произошло переполнение и результат получился некорректным.
- Флаг OF обозначает переполнение для чисел со знаком.
- Флаг SF равен знаковому биту результата (естественно, для чисел со знаком, а для беззнаковых он равен старшему биту и особо смысла не имеет).
- Флаг ZF устанавливается, если результат равен 0.
- Флаг PF — признак чётности, равен 1, если результат содержит нечётное число единиц.
add ax ,5 ; AX = AX + 5
add dx,cx ;DX = DX + CX
add dx,cl ;Ошибка: разный размер операндов.
7.1.2. SUB — команда для вычитания одного числа из другого. Она работает как с числами со знаком, так и без знака.
SUB Приемник , Источник
Логика работы команды:
<Приемник> = <Приемник> — <Источник>
Возможные сочетания операндов для этой команды аналогичны команде MOV .
По сути дела, это – команда вычитания с присвоением, аналогичная принятой в языке C / C ++:
Приемник -= Источник;
Операнды должны иметь одинаковый размер. Результат помещается на место первого операнда.
На самом деле вычитание в процессоре реализовано с помощью сложения. Процессор меняет знак второго операнда на противоположный, а затем складывает два числа.
sub ax ,13 ; AX = AX — 13
sub ax , bx ; AX = AX + BX
sub b x,cl ;Ошибка: разный размер операндов.
7.1.3. Инкремент и декремент. Очень часто в программах используется операция прибавления или вычитания единицы. Прибавление единицы называется инкрементом, а вычитание — декрементом. Для этих операций существуют специальные команды процессора: INC и DEC. Эти команды не изменяют значение флага CF.
Эти команды содержит один операнд и имеет следующий синтаксис:
INC Операнд
DEC Операнд
Логика работы команд:
INC : <Операнд> = < Операнд > + 1
DEC : <Операнд> = < Операнд > — 1
В качестве инкремента допустимы регистры и память: reg , mem .
inc ax ; AX = AX + 1
dec ax ; AX = AX — 1
7.1.4. NEG – команда для изменения знака операнда.
NEG Операнд
Логика работы команды:
<Операнд> = – < Операнд >
В качестве декремента допустимы регистры и память: reg , mem .
7.2. Сложение и вычитание с переносом.
В системе команд процессоров x86 имеются специальные команды сложения и вычитания с учётом флага переноса (CF). Для сложения с учётом переноса предназначена команда ADC, а для вычитания — SBB. В общем, эти команды работают почти так же, как ADD и SUB, единственное отличие в том, что к младшему разряду первого операнда прибавляется или вычитается дополнительно значение флага CF.
Они позволяют выполнять сложение и вычитание многобайтных целых чисел, длина которых больше, чем разрядность регистров процессора (в нашем случае 16 бит). Принцип программирования таких операций очень прост — длинные числа складываются (вычитаются) по частям. Младшие разряды складываются(вычитаются) с помощью обычных команд ADD и SUB, а затем последовательно складываются(вычитаются) более старшие части с помощью команд ADC и SBB. Так как эти команды учитывают перенос из старшего разряда, то мы можем быть уверены, что ни один бит не потеряется. Этот способ похож на сложение(вычитание) десятичных чисел в столбик.
На следующем рисунке показано сложение двух двоичных чисел командой ADD:

При сложении происходит перенос из 7-го разряда в 8-й, как раз на границе между байтами. Если мы будем складывать эти числа по частям командой ADD, то перенесённый бит потеряется и в результате мы получим ошибку. К счастью, перенос из старшего разряда всегда сохраняется в флаге CF. Чтобы прибавить этот перенесённый бит, достаточно применить команду ADC:
Как сложить 2 двоичных числа в ассемблере
На этом шаге мы познакомимся с правилами выполнения действий с двоичными числами.
Так как компьютер может различить только нулевое и единичное состояние бита, то он работает в системе счисления с основанием 2 или в двоичной системе . Бит получил свое название от английского Binary digit ( двоичная цифра ) .
Сочетанием двоичных цифр (битов) можно представить любое значение. Значение двоичного числа определяется относительной позицией каждого бита и наличием единичных битов. Ниже показано восьмибитовое число, содержащее все единичные биты:
Самая правая цифра имеет весовое значение 1, следующая цифра влево — 2, следующая — 4 и т.д. Общая сумма для восьми единичных битов в данном случае составит 255 (1+2+4+8+16+32+64+128=255).
Компьютер выполняет арифметические действия только в двоичном формате. Поэтому, программируя на языке Ассемблер, необходимо знать правила сложения в двоичной системе счисления. Напомним их:
Проиллюстрируем использование этих правил на конкретном примере.
Пример: сложить числа 65 и 42, представленные в двоичной системе счисления. В десятичной системе счисления все осуществляется достаточно просто: 65+42=107.
Для сложения этих чисел в двоичной системе счисления нужно сначала перевести их в эту систему:
Рис.1. Алгоритм перевода числа из десятичной в двоичную систему счисления
Таким образом, получаем: 65 10 = 01000001 2 . Обратите внимание на то, что ведущий ноль в двоичном представлении числа добавлен для дополнения двоичного представления до восьми бит.
Аналогично: 42 10 = 00101010 2 . Выполним сложение этих чисел:
Можно убедиться, что 01101011 2 =107 10 :
Мы рассмотрели сложение чисел в компьютере. А как же осуществляется вычитание? Для выполнения операции вычитания оно заменяется сложением, а в качестве второго слогаемого берется противоположное число. Например, пусть надо выполнить вычитание: 65 — 42. Заменим его сложением: 65 + (-42). Но как получить соответствующее двоичное отрицательное число? Этот вопрос мы сейчас рассмотрим.
- взять соответствующее положительное число и инвертировать его биты (1 заменить на 0 и наоборот);
- к полученному числу прибавить 1.
Приведем пример использования рассмотренного алгоритма.
Пример 1. Получить двоичное представление числа -65. Напомним, что 65 10 = 01000001 2 . Инвертируем биты: 10111110 . К полученному числу прибавим 1: 10111110+1=10111111 . Убедимся в правильности представления. Сумма +65 и -65 должна составить нуль:
Все восемь бит имеют нулевое значение. Пока будем считать, что полученная единица, перенесенная влево, потеряна.
Это правило позволяет выполнять вычитание чисел в двоичной системе счисления: вычитание заменяется сложением и в качестве второго слагаемого берется отрицательное число.
Пример 2. Вычесть из 65 число 42. Двоичное представление для 42 — это 00101010, а для -42 двоичное представление будет следующим — 11010110:
Пример 3. Какое значение необходимо прибавить к двоичному числу 00000001, чтобы получить число 00000000? В терминах десятичного счисления ответом будет число -1. Для двоичного счисления это число 11111111:
В заключение приведем фрагмент уменьшающегося ряда чисел в двоичном представлении:
На следующем шаге мы познакомимся с шестнадцатеричным представлением чисел.