Разное

Сложение в ассемблере: Как сложить два числа в Ассемблере

Как сложить два числа в Ассемблере

Главная / Ассемблер / Примеры (исходники) /


Как выучить английский

В наше время любой человек должен знать английский язык. А тем более программист. Потому что довольно большая часть документации существует только на английском. А профессионал не может ждать, пока кто-то переведёт ему документацию. Он должен уметь быстро получать нужную инфорамцию и использовать её, независимо от того, на каком она языке — на английском или на русском… Ссылки на курсы по английскому…

Складывать числа в ассемблере не так уж и сложно. В подавляющем большинстве случаев это делается с помощью команды ADD. Но в любой задаче, даже самой простой, могут встретиться неожиданности, которые не может предусмотреть новичок в силу того, что не имеет достаточного опыта и знаний.

Поэтому, несмотря на то, что в описании инструкции ADD всё достаточно понятно, я решил написать небольшую статью с примерами.

Итак, первое, что нам надо помнить — это размер числа. Если мы складываем два числа, то размер результата может быть больше, чем размер регистра, в который помещается результат.

Второе — мы можем складывать и отрицательные числа. Следовательно, и результат может быть отрицательным.

И да — сложение положительного и отрицательного чисел — это, по сути, вычитание одного числа из другого. Хотя для вычитания в ассемблере есть команда SUB.

Команда ADD существует с незапамятных времён — ещё с процессора 8086. Поэтому она поддерживается и всеми последующими процессорами Интел и совместимыми.

Простейший пример использования:


MOV  AL, 3
ADD  AL, 2    ; AL = 3 + 2 = 5

Здесь мы сначала записали число 3 в регистр AL, а затем применили команду ADD для сложения числа в AL с числом 2. Результат записывается в нашем случае в AL. И там после выполнения команды будет число 5.

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


MOV  BX, 7
MOV  AX, 2
ADD  AX, BX   ; AX = 7 + 2 = 9

Также вместо регистров можно использовать память:


MOV  [110h], 3
ADD  [110h], 2  ; По адресу [110h] теперь хранится 5
MOV  AL, 1
ADD  AL, [110h] ; AL = 6

При работе с памятью, конечно, надо понимать, что находится по данному адресу и к каким последствиям может привести прямое обращение к памяти и изменение её содержимого. В данном примере на это мы внимания не обращаем. Это просто пример.

Складывать можно не только константы, регистры и память, но и переменные:


ADD  BL, MyVar
ADD  MyVar, 3

Не знаю, во всех ли ассемблерах это будет работать. Но в эмуляторе точно работает. Причём оба варианта. То есть можно записывать результат как в регистр, так и в переменную.

Есть ещё такая тема, как сложение с переносом. Но в этой статье рассматривать её не будет. Больше сведений об этом можно найти здесь.

И есть ещё такая вещь, как BCD-значения. Инструкции для работы с такими значениями: AAA, AAD, AAS, AAM.

На этом пока всё. Подключайтесь к группе Основы программирования в Телеграм, или к другим каналам (ссылки ниже), чтобы ничего не пропустить.


Подписаться на канал в РУТуб

Вступить в группу «Основы программирования»

Подписаться на рассылки по программированию


Учимся программировать

 

М. Иванюшин
    • Сложение
    • Вычитание
    • Умножение
    • Деление
    • Преобразование чисел

     В одном из предыдущих разделов были опубликованы коды нескольких полезных программ. Но команды, при помощи которых написаны эти программы, оказались скрыты для вас. Здесь мы попробуем показать вам «кухню программирования» и рассмотрим программы сложения, вычитания, умножения, деления, преобразования шестнадцатеричных чисел в десятичные и преобразования десятичных в шестнадцатеричные.

     Сложение
     Для сложения однобайтных чисел в наборе команд микропроцессора КР580ВМ80А есть стандартные команды ADD и ADC, сложение двухбайтных чисел выполняется при помощи команды DAD. Но если складываемые числа превосходят два байта, то для сложения надо писать специальную программу. Приведенная ниже программа складывает трехбайтные числа:

;СЛОЖЕНИЕ ТРЕХБАЙТНЫХ ЧИСЕЛ
;вход в программу:
;первое слагаемое SL0, SL1, SL2;
;второе слагаемое SL3, SL4, SL5;
;результат работы:
;сумма SL3, SL4, SL5;
SUMMA3: LHLD SLO XCHG ;D,E — младшие ;байты первого ;слагаемого LHLD SL3 ;H,L — младшие ;байты второго ;слагаемого DAD D ;H,L — сумма этих ;младших байтов.
;Если при сложении ;возникнет перенос, ;он будет в даль- ;нейшем учтен в ;команде ADC M SHLD SL3 ;сохранили в памяти ;первые два ;байта результата LDA SL2 ;в регистре А ;старший байт ;первого слагаемого LXI H,SL5 ;H,L — адрес ;старшего байта ;второго слагаемого ADC M ;сложение старших ;байтов слагаемых. ;Учтен перенос, ;если он был при ;сложении командой DAD MOV M,A ;результат в SL5 RET

     Вычитание
     Для вычитания в наборе команд микропроцессора есть две команды SUB и SBB, работают они только с байтами, для обработки же многобайтных чисел надо писать программу.

Вычитание одного двухбайтного числа из другого можно организовать, например, так:

;ВЫЧИТАНИЕ ДВУХБАЙТНЫХ ЧИСЕЛ
;вход в программу:
;H,L - уменьшаемое, 
;D,E - вычитаемое,
;результат работы:
;В,С - разность.
VICh3: MOV A,L ;ВЫЧИТАНИЕ МЛАДШИХ БАЙТОВ SUB E MOV С,А ;ВЫЧИТАНИЕ СТАРШИХ БАЙТОВ MOV А,Н SBB D ;учитывается перенос, ;если он был ;при обработке ;младших байтов MOV В,А RET

     Для вычисления разности трехбайтных чисел можно использовать следующую программу:

;ВЫЧИТАНИЕ ТРЕХБАЙТНЫХ ЧИСЕЛ
;вход в программу:
;уменьшаемое SL3,SL4,SL5,
;вычитаемое SL0,SL1,SL2,
;результат работы:
;разность SL3,SL4,SL5.
VICh4: LXI H,SL0 ;HL — адрес млад- ;шего байта ;вычитаемого LXI D,SL3 ;DE — адрес млад- ;шего байта ;уменьшаемого LDAX D ;A — младший байт ;уменьшаемого SUB М STAX D ;вычислен и сохранен ;младший байт ;разности INX D ;DE — адрес байта SL4 INX H ;HL — адрес байта SL1 LDAX D SBB M STAX D ;в SL4 второй байт ;разности INX H INX D LDAX D SBB M STAX D ;в SL5 третий байт ;разности RET

     Умножение
     Микропроцессор КР580ВМ80А не имеет команд умножения, поэтому для выполнения этой математической операции надо составлять программу.

     Приведенная здесь программа работает по следующему алгоритму:
     Шаг 1: проверить младший бит множителя. Если он равен нулю, перейти к шагу 3, если единице — сложить множимое с промежуточным результатом умножения.
     Шаг 2: сдвинуть полученный промежуточный результат на один бит влево.
     Шаг 3: повторять шаги 1 и 2 до тех пор, пока не будут проверены все биты множителя.

;УМНОЖЕНИЕ
;вход в программу: 
;А - множитель, DE — множимое, 
;результат работы: 
;HL - произведение
UMNOG: LXI Н,0 ;сброшен промежу- ;точный результат ;****** шаг 3 ****** SHAG3: ORA А ;проверка оконча- ;ния работы RZ ;если содержимое ;регистра А ;равно нулю — ;умножение закончено ;****** шаг 1 ******
RAR ;младший бит мно- ;жителя в переносе INC SDVIG ;если перенос ;равен нулю — ;пропуск сложения DAD D ;сложение множи- ;мого и промежуточ- ;ного результата ;******шаг 2 ****** SDVIG: XCHG DAD H ;сдвиг множимого XCHG JMP SHAG3

     В строке с меткой SHAG3 проверка на равенство нулю аккумулятора выполнена при помощи логической операции ИЛИ аккумулятора с самим собой. Эта операция не изменяет содержимое аккумулятора, но устанавливает все признаки. Можно было бы проверить содержимое аккумулятора на равенство нулю при помощи команды CPI 00, но эта команда занимает больше места в памяти и дольше выполняется.

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

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

;ДЕЛЕНИЕ ЧЕТЫРЕХБАЙТНОГО ЧИСЛА 
;НА ЧЕТЫРЕХБАЙТНОЕ
;вход в программу: 
;DE - адрес делимого, 
;HL - адрес делителя, 
;результат работы: 
;RES —частное, 
;DE — адрес остатка.  
DELEN: XRA А STA RES STA RES+1 STA RES+2 STA RES+3 ;сброшено значение ;частного ;ЗАПИСЬ ДЕЛИТЕЛЯ В ЯЧЕЙКУ DEL MOV A,M STA DEL INX H MOV A,M STA DEL+1 INX H MOV A,M STA DEL+2 INX H MOV A,M STA DEL+3 INX H MOV A,M STA DEL+4 LXI H,RES ;вычитание делимого из делителя Rl: LDA DEL MOV C,A LDA DEL+1 MOV B,A LDAX D SBB С STAX D INX D LDAX D SBB В STAX D INX D LDA DEL+2 MOV C,A LDA DEL+3 MOV B,A LDAX D SBB С STAX D INX D LDAX D SBB В STAX D DCX D DCX D DCX D ;восстановлено ;исходное значение ;регистров DE JC KD ;если перенос уста- ;новлен, значит ;делитель стал ;больше делимого PUSH PSW ;запомнено состояние ;переноса ;подсчет числа вычитаний ;делителя из делимого ;HL — адрес результата DELI: INR M JNZ R3 INX H ;если установлен ;признак равенства ;нулю, значит, в ;результате выполнения ; команды INR M ;возник перенос и ;его надо учесть INR М ;увеличен на единицу ;следующий байт ;результата JNZ R2 INX H INR M DCX H ;восстановление ;исходного значения R2: DCX H ;регистров HL R3: POP PSW ;восстановлен ;текущий перенос ;для правильного ;выполнения сложения ;в цикле R1 JMP R1 ;ВОССТАНОВЛЕНИЕ ОСТАТКА KD: LDA DEL MOV C,A LDA DEL+1 MOV B,A LDAX D ADD С STAX D INX D LDAX D ADC В STAX D INX D LDA DEL+2 MOV C,A LDA DEL+3 MOV B,A LDAX D ADC С STAX D INX D LDAX D ADC В STAX D DCX D DCX D DCX D ;DE — адрес остатка RET

     Преобразование чисел
     Люди привыкли работать с десятичными числами, а вычислительные машины работают только с двоичными, поэтому, если требуется отображать результаты работы ЭВМ в десятичном виде или преобразовывать вводимые десятичные числа в двоичный формат, необходимы специальные программы.
     В вычислительной технике есть понятие двоично-десятичного числа. Двоично-десятичным числом называется число, в котором каждые четыре бита представляют десятичную цифру от 0 до 9. Например, двоичное число 00001111 в двоично-десятичном виде будет 00010101.
     Суть описываемой программы преобразования двоичного числа в двоично-десятичное заключается в том, что двоичное число, которое в обычном виде выглядит так:

      двоичное число:
              бит7 * 27 + бит6 * 26 + бит5 * 25 + бит4 * 24 +
             + бит3 * 23 + бит2 * 22 + бит1 * 21 + бит0 * 20
преобразуется к виду:
      десятичное число:
           ((((((бит7 * 2 + бит6) * 2 + бит5) * 2 + бит4) * 2 + 
                + бит3) * 2 + бит2) * 2 + бит1) * 2 + бит0.

;ПРЕОБРАЗОВАНИЕ ДВОИЧНОГО ЧИСЛА 
;В ДВОИЧНО-ДЕСЯТИЧНОЕ
;BCD2B - программа перевода двухбайтного
;двоичного числа в двоично-десятичное. 
;Двоичное число передается
;в регистрах HL, 
;результат работы:
;А - десятки тысяч,
;В - тысячи и сотни,
;С - десятки и единицы.
;BCD1B - программа перевода однобайтного
;числа в двоично-десятичный код.
;Двоичное число записывается
;в регистр Н, регистр L сбрасывается.
;результат работы:
;А - разряды сотен,
;В - разряды десятков и единиц.
BCD2B:    MVI Е,17     ;установка счетчика
                       ;первого цикла
          CALL CONV    ;вычисление младшего 
                       ;двоично-десятичного байта
          MOV С,А      ;вычисленный результат сохранен
          MVI Е,17     ;установка счетчика
                       ;второго цикла 
          JMP PROD
BCD1B:    MVI E,9      ;установка счетчика 
                       ;для программы BCD1B 
          CALL CONV    ;вычисление двух
                       ;старших байтов
          MOV В,А      ;запомнен промежуточный 
                       ;двоично-десятичный результат
          MOV A,L      ;установка старшего 
                       ;двоично-десятичного байта 
          RET 
CONV:     XRA А        ;сброс регистра А в нуль
SBIT:     DCR E        ;уменьшение на 1 
                       ;счетчика числа циклов 
          RZ
          DAD H        ;сдвиг старших разрядов 
                       ;в перенос 
          ADC A 
          DAA          ;двоично-десятичная коррекция
          JNC SBIT     ;двоично-десятичный 
                       ;байт больше 99?
          INX H        ;да 
          JMP SBIT

     Обратите внимание, как в строке с меткой CONV: устанавливается в нуль регистр А. Операция ИСКЛЮЧАЮЩЕЕ ИЛИ аккумулятора с самим собой обнулит его, а также сбросит и бит переноса.
     Приведенные программы полезны, если необходимо выводить на экран результаты вычислений. А как быть, если необходимо преобразовать однобайтное или двухбайтное десятичное число в двоичное? Это не сложно. Для этого надо выделить биты, определяющие десятки тысяч, и умножить их на 10000, затем выделить биты, определяющие тысячи, и умножить на 1000, выделить сотни и умножить на 100, выделить десятки и умножить на 10, и, наконец, выделить единицы. Сложение всех этих чисел даст нужный результат.
     Все эти действия выполняет следующая программа.

;вход в программу: 
;А - десятки тысяч, 
;В - тысячи и сотни,
;С - десятки и единицы.
;результат работы:
;HL - двоичное число.
DVH: LXI D,10000 CALL UMNOG PUSH H ;обработаны десятки тысяч ;и сохранены в стеке MOV А,В ;разряды тысяч занимают ;четыре старших бита RAR RAR RAR RAR ;разряды тысяч в ;младших битах ANI 0FH ;выделены разряды тысяч LXI D,1000 CALL UMNOG ;обработаны разряды тысяч POP D ;DE — предыдущий результат DAD D PUSH H MOV A,B ANI 0FH ;выделены разряды сотен LXI D,100 CALL UMNOG POP D DAD D PUSH H MOV A,C RAR RAR RAR RAR ANI 0FH ;выделены разряды десятков LXI D,10 CALL UMNOG POP D DAD D MOV A,C ANI 0FH ;выделены разряды единиц MOV E,A MVI D,0 DAD D ;HL — исходное число ;в двоичном виде RET

     Заключение
     Разберитесь, как работают эти программы, поскольку изучение хорошо прокомментированных программ позволяет быстро научиться писать программы самим. И еще совет: если вы хотите всерьез заниматься вычислительной техникой, собирайте различные прикладные программы — математические вычисления, обработка данных и т.п. Это позволит вам со временем сформировать полезную библиотеку программ.


Что такое арифметические инструкции на языке ассемблера?

Хизар Хаят Саани

Устали от LeetCode? 😩

Изучите 24 шаблона, чтобы решить любой вопрос на собеседовании по кодированию, не заблудившись в лабиринте практических задач в стиле LeetCode. Практикуйте свои навыки в практической среде кодирования, не требующей настройки. 💪

Язык ассемблера — это язык программирования низкого уровня. Инструкции на языке ассемблера аналогичны инструкциям машинного кода.

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

В этом кадре мы будем обсуждать арифметические инструкции на языке ассемблера архитектуры машины x86 .

Типы арифметических инструкций

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

  1. Сложение ( добавить )
  2. Вычитание ( sub )
  3. Умножение ( mul )
  4. Отдел ( отдел )

Сложение и вычитание

Синтаксис для написания инструкций сложения или вычитания следующий:

 назначение операции, источник
 
  • операция: предполагаемая арифметическая операция, т. е. добавить или заменить .

  • назначение: регистр аккумулятора или ячейка памяти, где мы будем хранить наш окончательный результат после добавления или вычитания значения в исходном регистре или ячейке памяти.

  • источник: регистр или ячейка памяти, которая содержит значение, которое должно быть добавлено или вычтено из исходного содержимого регистра назначения .

Назначение и источник могут быть комбинацией следующего:

1. Зарегистрируйтесь, чтобы зарегистрировать

 mov ax, 10 # переместите 10, чтобы зарегистрировать 'ax'
mov bx, 5 # переместите 5, чтобы зарегистрировать 'bx'
добавить топор, бх
 

2. Память для регистрации

 mov ax, 10 # перемещение 10 для регистрации 'ax'
add axe, [num1] # доступ к значению, хранящемуся в ячейке num1, и сохранение суммы
               # снова в регистре 'ax'
 

3. Зарегистрировать в памяти

 mov ax, 10
добавить [число1], топор
 

4. Константа для регистрации

 mov ax, 10
add ax, 5 # добавить 5 к значению регистра 'ax' и сохранить сумму в 'ax'
 

5. Константа в память

 добавить [num1], 5 # добавить 5 к значению, хранящемуся в num1, и заменить значение
              # там с суммой
 

Мы также можем применить вышеуказанные комбинации источника/получателя к умножению и делению, где это применимо.

Дополнительные инструкции языка ассемблера, сопоставленные с языком высокого уровня

Увеличение и уменьшение

Инструкции inc и dec могут использоваться для inc rement или dec rement содержимое соответствующих операндов на единицу.

Инструкция inc не влияет на флаг переноса.

Инструкция dec устанавливает флаг нуля , если результат операции равен 0 .

Умножение и деление

Синтаксис для записи инструкций умножения или деления следующий:

 источник операции
 

мул выполняет беззнаковое умножение исходного операнда и аккумулятора.

Если исходным операндом является байт (8 бит), мы умножаем его на значение, хранящееся в регистре AL . Результат возвращается в регистры AH и AL . Старшая половина 16-битного результата сохраняется в AH , а младшая половина — в AL . Это означает, что если результат достаточно мал, чтобы быть представленным в 8 битах, AH будет содержать 0 .

Если исходным операндом является слово (16 бит), то мы умножаем его на значение, хранящееся в регистре AX и результат возвращается в регистры DX и AX . Старшая половина 32-битного результата сохраняется в DX , а младшая половина — в AX .

Варианты инструкции mul

div выполняет целочисленное деление аккумулятора и исходного операнда. Результат состоит из целочисленного частного и остатка.

Если исходным операндом является байт, 16-битное число, хранящееся в AX , делится на операнд. 8-битное частное хранится в AL , а 8-битный остаток в AH .

Если исходным операндом является слово, 32-битное число, хранящееся в DX : AX , делится на операнд. Старшая половина числа хранится в DX , а младшая — в AX . 16-битное частное хранится в AX , а остаток в ДХ .

Варианты инструкции div

Код

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

 

# программа для отображения арифметических инструкций в AL

# дополнение

# load ax, 5 # load ax, 5 # число в ax

mov bx, 2 # число загрузки в bx

add ax, bx # накопление суммы в ax

# вычитание

mov cx, 10

mov dx, 3

# накопление разности sub cx, dx в сх

# освежающие регистры

Move Axe, 0

Mov BX, 0

Mov CX, 0

MOV DX, 0

# Умножение - 8 -битный источник

MOV, 5

MOV BL, 10

mul bl # результат в ax

# обновление регистров

mov ax, 0

mov bx, 0

# умножение - 16-битный источник in dx:ax

# обновление регистров

MOV AX, 0

MOV BX, 0

# Divison - 8 -битный источник

MOV AL, 23

MOV BL, 4

DIV BL # COUTITION в AL, оставшееся в AH

# Регистры обновления

mov ax, 0

mov bx, 0

# деление - 16-битный источник завершить программу

int 0x21

СВЯЗАННЫЕ ТЭГИ

язык ассемблера

УЧАСТНИК

Хизар Хаят Саани

Copyright © 2023 Educative, Inc. Все права защищены раздел .текст глобальный _start _Начало: мов акс,4 мов ebx,2 ;добавление добавить eax, ebx добавить eax,’0′ mov [сумма],eax ;печатать сообщение мов эдкс, лен mov ecx, msg мов ebx,1 мов акс,4 интервал 0x80 ;печатать сумму мов эдкс, 1 mov ecx, сумма мов ebx,1 мов акс,4 интервал 0x80 ;выход мов ebx,0 мов акс,1 интервал 0x80 раздел .данные msg db «Сумма:» len equ $ — msg раздел .bss сумма соотв. 1


STDIN

STDIN

Вывод:

 Сумма: 6 

создано 8 месяцев назад Venom Viper

Пишите, запускайте и делитесь кодом сборки онлайн с помощью онлайн-компилятора OneCompiler’s Assembly бесплатно. Это один из надежных, многофункциональных онлайн-компиляторов для языка ассемблера. Начать работу с компилятором сборки OneCompiler просто и довольно быстро. Редактор показывает образец стандартного кода, когда вы выбираете язык как Assembly и приступайте к кодированию.

Язык ассемблера (asm) — это язык программирования низкого уровня, в котором языковые инструкции будут больше похожи на инструкции машинного кода.

Каждый ассемблер может иметь свой язык ассемблера, предназначенный для конкретного компьютера или операционной системы.

Язык ассемблера требует меньше времени выполнения и памяти. Это более полезно для прямого манипулирования оборудованием, критически важных приложений в реальном времени. Используется в драйверах устройств, низкоуровневых встраиваемых системах и т. д.

Язык ассемблера обычно состоит из трех разделов,

  1. Раздел данных

    Для инициализации переменных и констант, размер буфера, эти значения не меняются во время выполнения.

  2. секция bss

    Для объявления переменных

  3. текстовая секция

    _start указывает начало этой секции, где фактически написан код.

Переменные

Существуют различные директивы определения для выделения пространства для переменных как для инициализированных, так и для неинициализированных данных.

1. выделить пространство для хранения на инициализированные данные

Синтаксис

.   1 байт     DW   Определить слово   2 байта     DD   Определить двойное слово  3 7 0370     DQ    Define Quadword    8 bytes        DT    Define Ten Bytes    10 bytes         

2. To allocate storage space to un-initialized data

Doubleword
Define Directive Описание
RESB Резерв a Байт
RESW Резерв a Word
RE 0375
RESQ Reserve a Quadword
REST Reserve a Ten Bytes

Constants

Constants can be defined using

1. equ

  • To define numeric constants
 CONSTANT_NAME EQU регулярное выражение или значение 

2.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *