Разное

Сложение двух чисел ассемблер: Сложение чисел на Assembler — CodeTown.ru

Содержание

Сложение на языке ассемблер — Altarena.ru — технологии и ответы на вопросы

Содержание

  1. Сложение на языке ассемблер
  2. Программирование на Ассемблере для начинающих с примерами программ
  3. IDE для Assembler
  4. Программа «Hello world» на ассемблере
  5. Сложение двух чисел на assembler
  6. Программа суммы чисел на ассемблере
  7. Получение значения из командной строки на ассемблере
  8. Циклы в ассемблере
  9. Сумма элементов массива на assembler
  10. Сложение чисел на Assembler
  11. Как создавать файлы Assembler
  12. Код сложения чисел на Assembler
  13. Как запускать программы
  14. Запуск отладчика OLLYDBG
  15. Команды сложения и вычитания
  16. Ассемблер. Арифметические инструкции
  17. Инструкция INC
  18. Инструкция DEC
  19. Инструкции ADD и SUB
  20. Инструкции MUL и IMUL
  21. Видео

Сложение на языке ассемблер

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

7.1.1. ADD – команда для сложения двух чисел. Она работает как с числами со знаком, так и без знака.

Логика работы команды:

По сути дела, это – команда сложения с присвоением, аналогичная принятой в языке C / C ++:

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

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

add dx,cx ;DX = DX + CX

add dx,cl ;Ошибка: разный размер операндов.

Логика работы команды:

По сути дела, это – команда вычитания с присвоением, аналогичная принятой в языке C / C ++:

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

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

sub b x,cl ;Ошибка: разный размер операндов.

7.1.3. Инкремент и декремент. Очень часто в программах используется операция прибавления или вычитания единицы. Прибавление единицы называется инкрементом, а вычитание — декрементом. Для этих операций существуют специальные команды процессора: INC и DEC. Эти команды не изменяют значение флага CF.

Эти команды содержит один операнд и имеет следующий синтаксис:

Логика работы команд:

7.1.4. NEG – команда для изменения знака операнда.

Логика работы команды:

7.2. Сложение и вычитание с переносом.

В системе команд процессоров x86 имеются специальные команды сложения и вычитания с учётом флага переноса (CF). Для сложения с учётом переноса предназначена команда ADC, а для вычитания — SBB. В общем, эти команды работают почти так же, как ADD и SUB, единственное отличие в том, что к младшему разряду первого операнда прибавляется или вычитается дополнительно значение флага CF.

Они позволяют выполнять сложение и вычитание многобайтных целых чисел, длина которых больше, чем разрядность регистров процессора (в нашем случае 16 бит). Принцип программирования таких операций очень прост — длинные числа складываются (вычитаются) по частям. Младшие разряды складываются(вычитаются) с помощью обычных команд ADD и SUB, а затем последовательно складываются(вычитаются) более старшие части с помощью команд ADC и SBB. Так как эти команды учитывают перенос из старшего разряда, то мы можем быть уверены, что ни один бит не потеряется. Этот способ похож на сложение(вычитание) десятичных чисел в столбик.

На следующем рисунке показано сложение двух двоичных чисел командой ADD:

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

//Сложение двух чисел с учетом переноса: FFFFFFAA + FFFF

Источник

Программирование на Ассемблере для начинающих с примерами программ

Многие считают, что Assembler – уже устаревший и нигде не используемый язык, однако в основном это молодые люди, которые не занимаются профессионально системным программированием. Разработка ПО, конечно, хорошо, но в отличие от высокоуровневых языков программирования, Ассемблер научит глубоко понимать работу компьютера, оптимизировать работку с аппаратными ресурсами, а также программировать любую технику, тем самым развиваясь в направлении машинного обучения. Для понимания этого древнего ЯП, для начала стоит попрактиковаться с простыми программами, которые лучше всего объясняют функционал Ассемблера.

IDE для Assembler

Первый вопрос: в какой среде разработки программировать на Ассемблере? Ответ однозначный – MASM32. Это стандартная программа, которую используют для данного ЯП. Скачать её можно на официальном сайте masm32.com в виде архива, который нужно будет распаковать и после запустить инсталлятор install.exe. Как альтернативу можно использовать FASM, однако для него код будет значительно отличаться.

Перед работой главное не забыть дописать в системную переменную PATH строчку:

Программа «Hello world» на ассемблере

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

Для начала запускаем редактор qeditor.exe в папке с установленной MASM32, и в нём пишем код программы. После сохраняем его в виде файла с расширением «.asm», и билдим программу с помощью пункта меню «Project» → «Build all». Если в коде нет ошибок, программа успешно скомпилируется, и на выходе мы получим готовый exe-файл, который покажет окно Windows с надписью «Hello world».

Сложение двух чисел на assembler

В этом случае мы смотрим, равна ли сумма чисел нулю, или же нет. Если да, то на экране появляется соответствующее сообщение об этом, и, если же нет – появляется иное уведомление.

Здесь мы используем так называемые метки и специальные команды с их использованием (jz, jmp, test). Разберём подробнее:

Программа суммы чисел на ассемблере

Примитивная программа, которая показывает процесс суммирования двух переменных:

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

Получение значения из командной строки на ассемблере

Одно из важных основных действий в программировании – это получить данные из консоли для их дальнейшей обработки. В данном случае мы их получаем из командной строки и выводим в окне Windows:

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

Здесь используется invoke – специальный макрос, с помощью которого упрощается код программы. Во время компиляции макрос-команды преобразовываются в команды Ассемблера. Так или иначе, мы пользуемся стеком – примитивным способом хранения данных, но в тоже время очень удобным. По соглашению stdcall, во всех WinAPI-функциях переменные передаются через стек, только в обратном порядке, и помещаются в соответствующий регистр eax.

Циклы в ассемблере

Для создания цикла используется команда repeat. Далее с помощью inc увеличивается значение переменной на 1, независимо от того, находится она в оперативной памяти, или же в самом процессоре. Для того, чтобы прервать работу цикла, используется директива «.BREAK». Она может как останавливать цикл, так и продолжать его действие после «паузы». Также можно прервать выполнение кода программы и проверить условие repeat и while с помощью директивы «.CONTINUE».

Сумма элементов массива на assembler

Здесь мы суммируем значения переменных в массиве, используя цикл «for»:

С помощью команды jne выполняется переход по метке, основываясь на результате сравнения переменных. Если он отрицательный – происходит переход, а если операнды не равняются друг другу, переход не осуществляется.

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

Источник

Сложение чисел на Assembler

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

Также напомню, что мы работаем в MASM32, и соответственно, вам необходимо его установить. Как это сделать, мы рассказывали в прошлой статье по Assembler.

Как создавать файлы Assembler

Прежде чем привести вам код программы, думаю, не лишним будет написать как и где прописывать код:

Не так важно с помощью какой программы вы это сделаете(блокнот, Notepad, и тд)

2. Пишем сам код в этом файле(пример кода будет ниже)

4. Перемещаем файл в папку BIN(папка, которую использовали в 1 статье)

Код сложения чисел на Assembler

Ну и собственно небольшой код программы:

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

Третья строчка — это раздел переменные( после этой строки, должны объявляться переменные), как вы видите, у нас в этой программе не будет переменных.

Четвертая — раздел кода. В нашей программе, мы помещаем в регистр eax значение 3, а затем с помощью add(прибавить) добавляем 2, логично, что теперь в этом регистре будет храниться значение 5.
Кто не знает, что такое регистр, то вам лучше почитать об этом здесь.
Затем идет команда ret, которая говорит о выходе из программы и сам выход end start.

Как запускать программы

1. Запускаем командную строку(прописать cmd в поиске, ну или другим способом)

2. Перейти в папку BIN с помощью команды cd

У меня эта команда будет выглядеть так: cd C:\Users\Никита\BIN

3. Пишем следующую запись: amake.bat имя файла(без расширения)

Я прописываю: amake.bat first

Также напомню вам, что это сработает только при правильно установленном MASM32, в предыдущей статье мы об этом говорили.

Жмем enter
Если ошибок не возникло то у вас появится что то вроде этого:

Запуск отладчика OLLYDBG

Программа скомпилировалась, а это уже хорошо, теперь нам нужно проверить как она сработала, вдруг она не сложила 2 числа.
Для этого в папке BIN открываем наш отладчик(который устанавливали в 1 статье) OLLYDBG.
В отладчике открываем файл программы (file > open first.exe), и видим наш код уже с другой стороны:

Так как мы работаем с регистром eax, то именно его значение и будем отслеживать.(в правом окне, 1 значение регистров)
Итак, чтобы пошагово прогнать нашу программу нужно нажать на 4 синию кнопку слева.(стрелка вниз с 3 точками)
После 1 нажатия, значение в eax стало равно 3, после 2 нажатия — 5.
Наша программа работает верно!

Итак, казалось бы простая программа сложения 2 чисел на Assembler, а сколько всего узнали! На сегодня все, оставляйте свои комментарии, если у вас есть вопросы или пожелания.

Источник

Команды сложения и вычитания

Лабораторная работа №2
«Изучение команд сложения и вычитания»

Цель работы: изучить форматы и правила работы с командами сложения и вычитания микропроцессора i8086.

Краткие теоретические сведения.

1. Форматы арифметических данных
2. Команды сложения
3. Команды вычитания
4. Команда обращения знака
5. Команды расширения знака

Коррекция результата сложения для представления в кодах ASCII и в упакованном десятичном формате (команды AAA и DAA).
Как уже упоминалось, при выполнении сложения микропроцессор 8×86 рассматривает операнды как двоичные числа. Что же произойдет, если они будут двоично-десятичными кодами чисел (кратко десятичными или BCD-числа¬ми)? Разберемся в этом на примере. При сложении упакованных BCD-чисел 26 и 55 микропроцессор 8×86 выполнит следующее двоичное сложение:

ADD AL,BL ;Сложить неупакованные числа, находящиеся в AL и BL
ААА ; и преобразовать результат в неупакованное число
Если результат превышает 9, то команда ААА добавляет 1 к содержимому регист¬ра АН (чтобы учесть избыточную цифру) и полагает флаг CF равным 1; в против¬ном случае она обнуляет флаг CF. Кроме того, команда ААА изменяет состояние флага AF и оставляет значения флагов PF, ZF, SF и OF неопределенными. Но так как в данном случае только флаг CF имеет смысл, то считайте значения остальных флагов уничтоженными.
Команда DAA преобразует содержимое регистра AL в две правильные упако¬ванные десятичные цифры. Она используется в следующем контексте:

ADD AL,BL ;Сложить упакованные BCD-числа в AL и BL
DAA ; и преобразовать результат в упакованное число
Если результат превышает предельное значение для упакованных BCD-чисел (99), то команда DAA добавляет 1 к содержимому регистра АН и полагает флаг CF равным 1. Кроме того, команда DAA изменяет состояния флагов PF, AF, ZF и CF и оставляет значение флага OF неопределенным. Но так как в данном случае только флаг CF имеет смысл, то считайте остальные пять флагов уничтоженными.

Как ни странно, приращение значения 8-битового регистра отнимает у микро¬процессора 8×86 больше времени, чем приращение значения 16-битового регистра. Это вызвано тем, что разра¬ботчики фирмы Intel предполагали, что программисты будут чаще пользоваться счетчиками размером в слово, а не байт, и предусмотрели специальную однобай¬товую версию команды INC для 16-битовых регистров.

0000 1010 (10)
+1111 1001 (-7)
0000 0011 (Ответ: 3)
Эврика! Мы получили правильный ответ!
Так как микропроцессор 8×86 выполняет дополнение до двух автоматически, то Вам эта операция понадобится в редких случаях. Позже в этом разделе мы рассмотрим команду NEG, посредством которой можно выполнить дополнение до двух, если оно когда-либо Вам понадобится.

приемник = приемник — источник

DEC CX ;Уменьшить знамение 16-битового
DEC AL ; или 8-битового регистра
DEC MEM_BYTE ;Уменьшить значение байта
DEC MEM_WORD[BX] ;или слова памяти

Команда обращения знака NEG.
Команда NEG вычитает значение операнда-приемника из нулевого значения и тем самым формирует его дополнение до двух. Команда NEG оказыва¬ет на флаг то же действие, что и команда SUB. Но поскольку один из операндов равен 0, то можно точнее описать условия изменения состояний флагов. Итак, при исполнении команды NEG флаги изменяются следующим образом:
Флаг переноса CF и флаг знака SF равны 1, если операнд представляет собой ненулевое положительное число; в противном случае они равны 0.
Флаг четности PF равен 1, если результат имеет четное число битов, равных 1; в противном случае он равен 0.
Флаг нуля ZF равен 1, если операнд равен 0; в противном случае он равен 0.
Флаг переполнения OF равен 1, если операнд-байт имеет значение 80Н или операнд-слово имеет значение 8000Н; в противном случае он равен 0.
Команда NEG полезна для вычитания значения регистра или ячейки памяти из непосредственного значения. Например, Вам нужно вычесть значение регистра AL из 100. Так как непосредственное значение не может служить приемником, то команда SUB 100, AL недопустима. В качестве альтернативы можно обратить знак содержимого регистра AL и добавить к нему 100:

Команда расширения знака.
Существуют две команды, позволяющие выполнять операции над смешанными данными за счет удвоения размера операнда со знаком. Команда CBW (convert byte to word — преобразовать байт в слово) воспроизводит 7-й бит регистра AL во всех битах регистра AH.
Команда CWD (convert word to double word — преобразовать слово в двойное слово) воспроизводит 15-й бит регистра AX во всех битах регистра DX.
Таким образом, команда CBW позволяет сложить байт и слово, вычесть слово из байта и т. д. Аналогично, команда CWD позволяет разделить слово на слово.
Приведем несколько примеров:

CBW ;Сложить байт в AL со словом в BX
ADD AX,BX
CBW ;Умножить байт в AL на слово в BX
IMUL BX
CWD ;Разделить слово в AX на слово в BX
IDIV BX

Индивидуальное задание.
Вычислить следующее выражение:

F = КОН1 оп1 (КОН2 оп2 Х оп3 Y) оп4 Z оп5 КОН3
где
КОН1, КОН2, КОН3 – числовые константы, согласно табл. 1
оп1, оп2, оп3, оп4, оп5 – операции сложения и вычитания согласно табл. 2
X, Y – переменные
Числовые константы из табл. 1 берутся согласно первой цифре варианта, операции сложения и вычитания из табл. 2 – согласно второй цифре варианта.
Исходные данные хранятся в памяти с адреса 0900H, вычисление выражения производится на Ассемблере, выводимые результаты — располагаются в памяти с адреса 1000Н.

КОН1
4589
КОН2
29
КОН3
562235
оп1

оп2

оп3
+
оп4
+
оп5
+
Пример. У студента индивидуальный вариант 9. Строим индивидуальное выражение для вычисления: F=458 – (481 + X + Y) + Z — 36

Источник

Ассемблер. Арифметические инструкции

На этом уроке мы будем разбираться с арифметическими инструкциями в ассемблере на примере INC, DEC, ADD, SUB и пр.

Инструкция INC

Инструкция INC (от англ. «INCREMENT») используется для увеличения операнда на единицу. Она работает с одним операндом, который может находиться либо в регистре, либо в памяти.

Синтаксис инструкции INC:

Операндом место_назначения может быть 8-битный, 16-битный или 32-битный операнд.

Инструкция DEC

Инструкция DEC (от англ. «DECREMENT») используется для уменьшения операнда на единицу. Она работает с одним операндом, который может находиться либо в регистре, либо в памяти.

Синтаксис инструкции DEC:

Операндом место_назначения может быть 8-битный, 16-битный или 32-битный операнд.

Инструкции ADD и SUB

Инструкции ADD и SUB используются для выполнения простого сложения/вычитания двоичных данных размером один byte, word или doubleword, то есть для сложения или вычитания 8-битных, 16-битных или 32-битных операндов, соответственно.

Синтаксис инструкций ADD и SUB:

ADD/SUB место_назначения, источник

Инструкции ADD/SUB могут выполняться между:

регистром и регистром;

памятью и регистром;

регистром и памятью;

памятью и константами.

Однако, как и для других инструкций, операции типа память-в-память невозможны с использованием инструкций ADD/SUB. Операции ADD или SUB устанавливают или сбрасывают флаги переполнения и переноса.

В следующем примере мы спрашиваем у пользователя два числа, сохраняем их в регистрах EAX и EBX, затем выполняем операцию сложения, сохраняем результат в ячейке памяти res и выводим его на экран:

Результат выполнения программы:

Enter a digit:
3
Please enter a second digit:
4
The sum is:
7

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

Результат выполнения программы:

Инструкции MUL и IMUL

Есть 2 инструкции для умножения двоичных данных:

инструкция MUL (от англ. «MULTIPLY») обрабатывает данные unsigned;

инструкция IMUL (от англ. «INTEGER MULTIPLY») обрабатывает данные signed.

Обе инструкции влияют на флаги переноса и переполнения.

Синтаксис инструкций MUL/IMUL:

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

Рассмотрим 3 разных сценария:

Сценарий №1: Перемножаются 2 значения типа byte. Множимое находится в регистре AL, а множителем является значение типа byte в памяти или в другом регистре. Результат произведения находится в AX. Старшие 8 бит произведения хранятся в AH, а младшие 8 бит хранятся в AL:

Сценарий №3: Перемножаются 2 значения типа doubleword. Множимое должно находиться в EAX, а множителем является значение типа doubleword, хранящееся в памяти или в другом регистре. Результат умножения сохраняется в регистрах EDX и EAX. Биты старшего порядка сохраняются в регистре EDX, а биты младшего порядка сохраняются в регистре EAX:

Источник

Видео

#6 Арифметические команды сложения ADD и ADC

FASM. add, sub, mul, div, neg. Арифметика ассемблер. #3

ЯЗЫК АССЕМБЛЕРА С НУЛЯ | #1 НАЧАЛО

Assembler — регистры и арифметические команды

Ассемблер. Урок 1. Основы. Арифметические операции.

#7 Арифметические команды вычитания SUB и SBB

Ассемблер (целочисленное сложение и вычитание)

Язык ассемблера для Intel x86 — Урок #3 — Регистры, команда mov, способы адресации, арифметика

Инструкция ADC

Сложен ли ассемблер? Команды ассемблера для микропроцессора Z80. Примеры программ в соотношении с C

Учебный курс. Часть 10. Сложение и вычитание с переносом

В системе команд процессоров x86 имеются специальные команды сложения и вычитания с учётом флага переноса (CF). Для сложения с учётом переноса предназначена команда ADC, а для вычитания — SBB. В общем, эти команды работают почти также, как ADD и SUB, единственное отличие в том, что к младшему разряду первого операнда прибавляется или вычитается дополнительно значение флага CF.

Зачем нужны такие команды? Они позволяют выполнять сложение и вычитание многобайтных целых чисел, длина которых больше, чем разрядность регистров процессора (в нашем случае 16 бит). Принцип программирования таких операций очень прост — длинные числа складываются (вычитаются) по частям. Младшие разряды складываются(вычитаются) с помощью обычных команд ADD и SUB, а затем последовательно складываются(вычитаются) более старшие части с помощью команд ADC и SBB. Так как эти команды учитывают перенос из старшего разряда, то мы можем быть уверены, что ни один бит не потеряется 🙂 Этот способ похож на сложение(вычитание) десятичных чисел в столбик.

На следующем рисунке показано сложение двух двоичных чисел командой ADD:

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

Аналогичная ситуация возникает с вычитанием чисел по частям. Чтобы было совсем понятно, приведу пример программы. Допустим, требуется вычислить значение формулы k=i+j-n+1, где переменные k, i, j и n являются 32-битными целыми числами без знака. Складывать и вычитать такие числа придётся в два этапа: сначала вычисления будут производиться с младшими словами операндов, а затем со старшими с учётом переноса.

Для прибавления единицы в данном примере нельзя использовать команду INC, так как она не влияет на флаг CF и мы можем получить ошибку в результате!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
use16                 ;Генерировать 16-битный код
org 100h              ;Программа начинается с адреса 100h
 
    mov ax,word[i]    ;Загружаем младшую часть i в AX
    mov bx,word[i+2]  ;Загружаем старшую часть i в BX
 
    add ax,word[j]    ;Складываем младшие части i и j
    adc bx,word[j+2]  ;Складываем старшие части i и j
 
    sub ax,word[n]
    sbb bx,word[n+2]  ;BX:AX = i+j-n
 
    add ax,1          ;Команда INC здесь не подходит!
    adc bx,0          ;BX:AX = i+j-n+1
 
    mov word[k],ax    ;\
    mov word[k+2],bx  ;/ Сохраняем результат в k
 
    mov ax,4C00h      ;\
    int 21h           ;/ Завершение программы
;-------------------------------------------------------
i dd 120000
j dd  80500
n dd   2300
k dd      ?

Запись word[i] означает, что мы переопределяем размер переменной (она объявлена как DWORD) и обращаемся к младшему слову. Старшее слово расположено в памяти после младшего, поэтому к адресу переменной надо прибавить 2, и соответствующая запись будет иметь вид word[i+2].

Посмотреть работу программы можно в отладчике:

Обратите внимание, как хранятся переменные в памяти. В процессорах Intel младший байт всегда хранится по младшему адресу, поэтому получается, что в окне дампа значения надо читать справа налево. В регистрах же числа записываются в нормальном виде. Сравните, как выглядит одно и то же значение k в памяти и в регистрах (старшая часть находится в BX, а младшая — в AX).

Одно из преимуществ ассемблера в том, что на нём можно реализовать работу с собственными форматами чисел, например с очень длинными целыми. А в языках высокого уровня выбор всегда ограничен компилятором. Следующая программа складывает два 7-байтных значения (для разнообразия я использовал только один регистр).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
use16                 ;Генерировать 16-битный код
org 100h              ;Программа начинается с адреса 100h
 
    mov ax,word[x]
    add ax,word[y]
    mov word[z],ax
 
    mov ax,word[x+2]
    adc ax,word[y+2]
    mov word[z+2],ax
 
    mov ax,word[x+4]
    adc ax,word[y+4]
    mov word[z+4],ax
 
    mov al,byte[x+6]
    adc al,byte[y+6]
    mov byte[z+6],al
 
    mov ax,4C00h      ;\
    int 21h           ;/ Завершение программы
;-------------------------------------------------------
x dd 0xF1111111
  dw 0xF111
  db 0x11
y dd 0x22222222
  dw 0x2222
  db 0x22
z rb 7

Обращение к старшему байту записывается как byte[x+6]. Наверно, вы уже догадались, почему 🙂 Команда MOV не меняет состояние флагов, поэтому её можно ставить между командами сложения.

Упражнение

Напишите программу для вычисления формулы d=b-1+a-c. Все числа — 3-х байтные целые без знака. Проверьте работу программы в отладчике. Результаты можете выкладывать в комментариях.

Следующая часть »

7.2 Содержание работы

Часть I. Процессор Cortex-M3. Программирование на ассемблере — 7

83

Из руководства по ассемблеру Help -> Assembler Reference Guide приведём пример использования макро. Следующий макрос определяет две различные реализации в зависимости от количества используемых аргументов:

SECTION MYCODE : CODE (2)

?add MACRO

a,b,c

IF _args <3

 

ADD

a,a, #b

ELSE

 

ADD

a,b, #c

ENDIF

 

ENDM

 

Если присутствуют два аргумента, то первый и второй аргументы складываются и эти команды воспринимаются как одинаковые:

main:

 

 

 

 

MOV

R1, #0xF0

 

 

?add

R1, 0xFF

;

это,

?add

R1, R1, 0xFF

;

и это,

add

R1, R1, #0xFF

; и это то же самое

Для более углублённого знакомства с макросредствами языка ассемблер нужно обратиться к упомянутому руководству. Здесь лишь заметим, что в нём нет «воды». Всё изложено очень кратко и доступно, примеры хорошо продуманы, IAR не зря так популярна. Недостаток всего один и то условный – руководство на английском языке. На крайний случай можно временно обратиться к русскому классику Юрову В.И. [7].

1.Изучите тему MACRO в руководстве по ассемблеру: Help -> Assembler Reference Guide , стр. 60 – 66. Освежите в памяти материал прошлых лабораторных работ. Пункт выполнить до занятий в аудитории.

2.Создайте новый проект. Используйте тот же пример:

3.SV2\exchange\_BNK\MCU\Milandr\Library.rar:Library\Examples\ 1986BE91_EVAL\PORT\Joystick_LEDs \main.c

4.Напишите код на Assembler-e, выполняющий сложение двух однозначных чисел, представленных в двоично-десятичном коде BCD.

5.Данный код оформите в виде макрокоманды и в виде функции.

6.Сравните время работы макрокоманды и функции, зажигая светодиод на отладочной плате. Для оценки времени вам потребуется написать ещё одну функцию на ассемблере, которая в цикле вызывает функцию сложения двух чисел, либо в том же цикле использует для этой цели макрокоманду. Время горения светодиода измеряйте с помощью ручных часов.

7.Решите ту же задачу определения времени работы макрокоманды и функции с помощью стандартных функций из библиотеки языка С. Сравните полученный результат. Если есть большое расхождение, попытайтесь его объяснить.

8.Запустите проект в симуляторе и снова измерьте время. Оцените, насколько точно моделируется работа микроконтроллера.

ТУСУР, «Миландр»

Каф. ЭСАУ

Недяк С.П., Шаропин Ю.Б

Февраль 2017 г.

Часть I. Процессор Cortex-M3. Программирование на ассемблере — 7

84

Сначала вспомним, что такое двоично-десятичный код (англ. binary-coded decimal) — BCD. Но прежде всего мы твёрдо усвоим разницу между понятиями «бит» и «разряд».

«Однако в один бит много информации не запишешь. Поэтому разработчики вычислительных машин организуют память так, чтобы её основная компонента, или слово, представляла собой группу битов, достаточную для солидной порции информации. »

Сингер М. Мини-ЭВМ PDP-11: программы на языке ассемблера и организация машины. / Перевод с англ. Каргашина А.Ю. и Миркотан А.С. под редакцией Баяковского Ю.М. – М: «Мир»,1984

Если немного перефразировать приведённую здесь цитату, то получится такая абракадабра: «Однако в один килограмм много веса не запихаешь, поэтому производители весов придумали центнер…»

Издание книги относится ко времени, когда мы усердно перенимали (по меткому замечанию Лебедева Сергея Алексеевича «передирали») зарубежный опыт в области создания вычислительной техники.

Бит – это единица измерения информации, т.е. количество информации как раз и измеряется в битах, количество бит может быть дробной величиной, как, например, килограмм – это единица измерения веса, а литр – это единица измерения объема, вес и объём могут измеряться дробными величинами.

Разряд (числовой) – это позиция или место цифры в позиционной системе счисления. Номер позиции всегда целая величина. В цифровой технике в основном используется двоичная система счисления. Это удобно. Разряд в данном случае ассоциируется с реальным логическим устройством, имеющим два устойчивых состояния. Мы можем сказать: « В 32-х разрядный регистр записано 8.3 бита информации». Максимальное количество информации, которое можно записать 32-х разрядный регистр, равно 32-м битам.

В силу этого замечательного факта понятия «бит» и «разряд» часто отождествляются.23 Для англоязычной публики такое простительно, а для русскоязычных студентов ТУСУРа рекомендуем прочесть книгу замечательных авторов [8].

Сразу же оговоримся. Мы тоже, следуя традиции, вместо слова «разряд» часто будем использовать слово «бит», но так , чтобы из контекста было понятно, когда речь идёт о реальном физическом носителе информации емкостью столько-то бит, а когда о количестве информации.

Вот теперь мы готовы к изучению BCD кодировки. Существует два формата этой кодировки: упакованный формат и неупакованный формат. Носитель информации емкостью в один байт или восемь бит состоит из двух тетрад, младшей и старшей. Тетрада (четвёрка) состоит из четырёх бит. Упакованный формат кодирует в одном байте две десятичные цифры, по одной цифре на тетраду, а неупакованный одну. Старшая (левая) тетрада в неупакованном формате всегда равна 0 и это поле из 4-х бит называется зоной.

Таким образом, упакованный формат кодирует в одном байте десятичные числа в диапазоне от 0 до 99, а неупакованный в диапазоне от 0 до 9. Приведём примеры в Таблице 1

23 Бит — англ. binary digit – двоичная цифр

ТУСУР, «Миландр»

Каф. ЭСАУ

Недяк С.П., Шаропин Ю.Б

Февраль 2017 г.

Часть I. Процессор Cortex-M3. Программирование на ассемблере — 7

85

Таблица 1 — Двоично-десятичное представление чисел

 

 

 

Число

Шестнадцатеричн.

 

Двоичный BCD-код

 

BCD-код

 

 

 

 

 

 

 

 

 

Упаков.

Неупак.

Упакованный

Неупакованный

0

00h

00h

0000 0000b

 

 

0000 0000b

3

03h

03h

0000

0011b

 

 

0000 0011b

63

63h

06 03h

0110

0011b

 

0000 0110 0000 0011b

863

08 63h

08 06 03h

0000 1000 0110

0011b

0000 1000

0000 0110

0000 0011b

В микропроцессорах INTEL есть специальные машинные команды для работы BCD-кодом. У ядра ARM Cortex-M3 такой возможности нет. В этой лабораторной работе мы напишем и испытаем на скорость работы функцию сложения двух однозначных чисел в BCD формате.

Cortex-M3 умеет складывать только числа, представленные в бинарном коде. Следовательно, выход у нас один – мы должны воспользоваться существующими командами и затем, если необходимо, скорректировать полученный результат.

Если сумма двух однозначных слагаемых не превышает 9, то ничего корректировать не нужно, результат в бинарном коде в точности совпадает с результатом в BCD-коде.

Если сумма превышает 9, то от результата нужно вычесть 10 и в старший байт записать 1, а в младшем оставить разность между полученной суммой и десятью. Так мы получим представление нашего результата в неупакованном BCD-коде.

Всё, что мы только что сказали, запишем на языке С.

Листинг

 

 

 

 

char * sum2BCD( char

a,

char b )

{

 

 

 

 

 

static char sum_ab[2];

sum_ab[0] =

a

+ b;

 

sum_ab[1] =

0;

 

)

if(

9 <

sum_ab[0]

{

sum_ab[0] -= 10;

 

sum_ab[1]

=

1 ;

}//if

 

 

 

 

return

&sum_ab[0];

 

 

}// sum2BCD

 

 

 

 

При обычной записи для выполнения арифметических вычислений мы размещаем старший разряд числа слева, а в памяти контроллера он будет располагаться справа, т. е. число 08 06 03 h в памяти будет располагаться как 03 06 08 h. Здесь действует правило: младший байт по младшему адресу. Так же будет располагаться и наш результат в массиве sum_ab[], младший байт (единицы) в 0-ом элементе массива, а старший (десятки) в 1-м.

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

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

В 5-й лабораторной работе мы уже однажды воспользовались этим методом. Но там мы из модуля (файла) на языке Си вызывали ассемблерную функцию. Сейчас мы должны сначала оценить скорость работы функции, а затем макрокоманды. Это можно сделать только в модуле на языке ассемблера, поскольку нельзя часть файла написать на языке С, а

ТУСУР, «Миландр» Каф. ЭСАУ Недяк С.П., Шаропин Ю.Б Февраль 2017 г.

Часть I. Процессор Cortex-M3. Программирование на ассемблере — 7

86

часть на ассемблере.

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

Листинг

 

 

PUBLIC

Funny

 

SECTION SSS : CODE (2)

Funny:

 

 

 

push

{r9,

LR }

;

mov

r9, #0x0493e0; 0x0493e0 = 300000

;mov

r9, #300000

; err ; инициализация параметра цикла

LOOP_:

 

 

; начало цикла

 

 

 

;

 

 

 

; код для исследования

;BL

 

 

;

sum2BCDf

; вызываем функцию sum2BCDf

 

 

 

;

 

 

 

; конец кода для исследования

subs

 

 

;

r9, r9, #1

; конец

BGT

LOOP

; цикла

pop

{ r9, PC }

; return

end

 

 

 

Обратите внимание на команды push и pop. В первой команде мы запоминаем адрес возврата в стеке, беря его из регистра связи LR, а во второй мы извлекаем его и загружаем в счётчик команд PC, т.е. осуществляем возврат. Регистр LR мы уже использовали при вызове функции sum2BCDf и этим действием затёрли адрес возврата. Поэтому осуществить возврат командой

BX LR

как мы это делали раньше, в данном случае уже нельзя.

Чтобы измерить время, мы должны проинициализировать параметр цикла так, чтобы время его работы было достаточным для измерения по обычным часам с секундной стрелкой. Затем нужно произвести два измерения: одно с работающим кодом, а второе с закомментированным. Разница времён, делённая на число циклов, и будет равна времени однократной работы интересующего нас участка кода.

На кафедральном сервере по адресу: \\SV2\exchange\_For_Students\MPSSAU\_Nediak\Arch

есть готовые примеры исходных кодов рассматриваемых здесь функций. Но вслед за Питером Нортоном и Джоном Соухэ [7.] мы вам советуем попытаться написать их самостоятельно, только так можно чему-нибудь научиться.

Очень ВАЖНОЕ Замечание!!

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

ТУСУР, «Миландр»

Каф. ЭСАУ

Недяк С.П., Шаропин Ю.Б

Февраль 2017 г.

x86 — СБОРКА — как сделать сумму между двумя числами (интервал)

Вот решение для EMU8086:

 .stack 100h
.данные
msj1 db 'Введите первое число: $'
msj2 db 'Введите второе число: $'
номер 1 дв ? ;ПЕРВЫЙ НОМЕР ИНТЕРВАЛА.
число2 дв ? ;ВТОРОЕ ЧИСЛО ИНТЕРВАЛА.
str db 6 ;МАКСИМАЛЬНОЕ РАЗРЕШЕННОЕ КОЛИЧЕСТВО СИМВОЛОВ (4).
      дб? ;КОЛИЧЕСТВО СИМВОЛОВ, ВВЕДЕННЫХ ПОЛЬЗОВАТЕЛЕМ. 
      db 6 dup (?) ;СИМВОЛЫ, ВВОДИМЫЕ ПОЛЬЗОВАТЕЛЕМ.
crlf db 13,10,'$' ;РАЗРЫВ СТРОКИ.
плюс db '+$' ;ЗНАК ПЛЮС ДЛЯ ОТОБРАЖЕНИЯ.
back db 8,'$' ;КУРСОР ПЕРЕМЕСТЕТСЯ НА ОДНУ МЕСТО НАЗАД (ВЛЕВО).
ekual db '=$' ;ЗНАК РАВНО ДЛЯ ОТОБРАЖЕНИЯ.
suma dw 0 ;СУММА ВСЕХ ЧИСЕЛ МЕЖДУ NUM1 И NUM2.
.код
;ИНИЦИАЛИЗИРОВАТЬ СЕГМЕНТ ДАННЫХ.
  мов топор, @данные
  мов дс, топор
;ОТОБРАЗИТЬ СООБЩЕНИЕ ДЛЯ ПЕРВОГО НОМЕРА.
  мов а, 9mov dx, смещение msj1
  через 21 час
;ЗАПИСАТЬ НОМЕР КАК СТРОКУ.
  мов ах, 0Ах
  mov dx, смещение ул
  через 21 час
;ПРЕОБРАЗОВАТЬ ЗАХВАЧЕННОЕ ЧИСЛО ИЗ СТРОКИ В ЧИСЛО.
  mov si, offset str ;ПАРАМЕТР ДЛЯ STRING2NUMBER.
  вызов string2number
  mov num1, bx ;ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ.
;ОТОБРАЗИТЬ ДВА РАЗРЫВА СТРОКИ.
  мов а, 9
  mov dx, смещение crlf
  через 21 час
  мов а, 9
  mov dx, смещение crlf
  через 21 час
;ОТОБРАЗИТЬ СООБЩЕНИЕ ДЛЯ ВТОРОГО НОМЕРА.
  мов а, 9
  mov dx, смещение msj2
  через 21 час
;ЗАПИСАТЬ НОМЕР КАК СТРОКУ.
  мов ах, 0Ах
  mov dx, смещение ул
  через 21 час
;ПРЕОБРАЗОВАТЬ ЗАХВАЧЕННОЕ ЧИСЛО ИЗ СТРОКИ В ЧИСЛО. 
  mov si, offset str ;ПАРАМЕТР ДЛЯ STRING2NUMBER.
  вызов string2number
  mov num2, bx ;ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ.
;ОТОБРАЗИТЬ ДВА РАЗРЫВА СТРОКИ.
  мов а, 9mov dx, смещение crlf
  через 21 час
  мов а, 9
  mov dx, смещение crlf
  через 21 час
;УБЕДИТЕСЬ, ЧТО ПЕРВОЕ ЧИСЛО МЕНЬШЕ ВТОРОГО.
  мов топор, число1
  cmp топор, число2
  jbe в порядке ;IF AX < NUM2 JUMP FINE.
  xchg ax, num2 ;ОБМЕН : NUM2=AX, AX=NUM2.
  mov число1, топор ;ЧИСЛО1=ЧИСЛО2.
отлично:
;ОТОБРАЗИТЬ ИНТЕРВАЛ.
  вызов display_interval
; ПОДОЖДИТЕ, ПОКА ПОЛЬЗОВАТЕЛЬ НАЖМЕТ ЛЮБУЮ КЛАВИШУ.
  мов ах, 7
  через 21 час
;ЗАВЕРШИТЬ ПРОГРАММУ.
  мов топор, 4c00h
  через 21 час
;------------------------------------------------------------------------
;ОТОБРАЗИТЬ ВСЕ ЧИСЛА МЕЖДУ ЧИСЛОМ1 И ЧИСЛО2
;ОТДЕЛЯЕТСЯ '+' И ОТОБРАЖАЕТ СУММУ
proc display_interval
интервал:
;ДОБАВИТЬ ТЕКУЩИЙ НОМЕР В СУММУ.
  mov ax, num1 ;AX = ТЕКУЩЕЕ ЧИСЛО.
  добавить суму, топор
;ПРЕОБРАЗОВАТЬ ТЕКУЩЕЕ ЧИСЛО В СТРОКУ ДЛЯ ЕГО ОТОБРАЖЕНИЯ.
  коллировать доллары ;ЗАПОЛНИТЬ "STR" С '$'.  НЕОБХОДИМО ДЛЯ ОТОБРАЖЕНИЯ.
  номер вызова2строка ;ПАРАМЕТР = AX. ВОЗВРАТ В ПЕРЕМЕННОЙ "STR".
;ЧИСЛО ОТОБРАЖЕНИЯ ПРЕОБРАЗОВАНО В СТРОКУ.
  мов а, 9mov dx, смещение ул
  через 21 час
;ОТОБРАЗИТЬ ЗНАК ПЛЮС.
  мов а, 9
  mov dx, смещение плюс
  через 21 час
;СЛЕДУЮЩИЙ НОМЕР ДЛЯ ОТОБРАЖЕНИЯ.
  вкл num1
  мов топор, число1
  cmp топор, число2
  jbe интервал ;IF AX <= NUM2 THEN REPEAT.
;ОТОБРАЗИТЬ СУММУ.
;ОТОБРАЗИТЬ BACKSPACE (ДЛЯ УДАЛЕНИЯ ПОСЛЕДНЕГО ЗНАКА ПЛЮС).
  мов а, 9
  mov dx, смещение назад
  через 21 час
;ОТОБРАЖАТЬ ЗНАК РАВНО.
  мов а, 9
  mov dx, смещение ekual
  через 21 час
;ПРЕОБРАЗОВАТЬ СУММУ В СТРОКУ, ЧТОБЫ ОТОБРАЗИТЬ ЕЕ.
  коллировать доллары ;ЗАПОЛНИТЬ "STR" С '$'. НЕОБХОДИМО ДЛЯ ОТОБРАЖЕНИЯ.
  мов топор, сума
  номер вызова2строка ;ПАРАМЕТР = AX. ВОЗВРАТ В ПЕРЕМЕННОЙ "STR".
;ЧИСЛО ОТОБРАЖЕНИЯ ПРЕОБРАЗОВАНО В СТРОКУ.
  мов а, 9mov dx, смещение ул
  через 21 час
  рет
конец
;------------------------------------------------------------------------
;ПРЕОБРАЗОВАТЬ СТРОКУ В ЧИСЛО BX. 
;SI ДОЛЖЕН ВВОДИТЬ, УКАЗЫВАЯ НА СТРОКУ.
proc string2number
;СДЕЛАЙТЕ SI, УКАЗЫВАЮЩИЙ НА НАИМЕНЕЕ ЗНАЧИМУЮ ЦИФРУ.
  inc si ;ПУНКТЫ НА КОЛИЧЕСТВО ВВОДИМЫХ СИМВОЛОВ.
  mov cl, [ si ] ;КОЛИЧЕСТВО ВВЕДЕННЫХ СИМВОЛОВ.
  mov ch, 0 ;ОЧИСТИТЬ CH, NOW CX==CL.
  добавить si, cx ;ТЕПЕРЬ SI УКАЗЫВАЕТ НА НАИМЕНЕЕ ЗНАЧИМУЮ ЦИФРУ.
;ПРЕОБРАЗОВАТЬ СТРОКУ.
  мов бх, 0
  mov bp, 1 ;УМНОЖЕНИЕ 10 ДЛЯ УМНОЖЕНИЯ КАЖДОЙ ЦИФРЫ.
повторение:
;ПРЕОБРАЗОВАТЬ СИМВОЛ.
  mov al, [ si ] ;ХАРАКТЕР В ОБРАБОТКЕ.
  sub al, 48 ;ПРЕОБРАЗОВАТЬ СИМВОЛ ASCII В ЦИФРУ.
  mov ah, 0 ;ОЧИСТИТЬ AH, NOW AX==AL.
  mul bp ;AX*BP = DX:AX.
  добавить bx,ax ;ДОБАВИТЬ РЕЗУЛЬТАТ К BX.
;УВЕЛИЧИТЬ НА 10 (1, 10, 100...).
  мов топор, бп
  мов бп, 10
  mul bp ;AX*10 = DX:AX.
  mov bp, ax ;НОВОЕ МНОЖЕСТВО 10.
;ПРОВЕРЬТЕ, ЗАКОНЧИЛИСЬ ЛИ МЫ.
  dec si ;СЛЕДУЮЩАЯ ЦИФРА ДЛЯ ОБРАБОТКИ.
  повтор цикла ;СЧЕТЧИК CX-1, ЕСЛИ НЕ НУЛЬ, ПОВТОРИТЬ.
  рет
конец
;------------------------------------------------------------------------
;ЗАПОЛНЯЕТ ПЕРЕМЕННУЮ STR '$'. 
;ИСПОЛЬЗУЕТСЯ ПЕРЕД ПРЕОБРАЗОВАНИЕМ ЧИСЕЛ В СТРОКУ, ПОТОМУ ЧТО
;ОТОБРАЖАЕТСЯ СТРОКА.
операционные доллары
  мов си, смещение ул
  мов сх, 6
шесть_долларов:
  мов бл, '$'
  мов [си], бл
  вкл си
  петля шесть_долларов
  рет
конец
;------------------------------------------------------------------------
;ЧИСЛО ДЛЯ ПРЕОБРАЗОВАНИЯ ДОЛЖНО ВВОДИТЬСЯ В AX.
;АЛГОРИТМ : ИЗВЛЕЧЬ ЦИФРЫ ПО ОДНОЙ, СОХРАНИТЬ
;ИХ В СТЕКЕ, ЗАТЕМ ИЗВЛЕЧЬ В ОБРАТНОМ
;ЗАКАЗ ПОСТРОИТЬ СТРОКУ (STR).
proc number2string
  mov bx, 10 ;ЦИФРЫ ИЗВЛЕЧАЮТСЯ ДЕЛЕНИЕМ НА 10.
  mov cx, 0 ;СЧЕТЧИК ИЗВЛЕЧЕННЫХ ЦИФР.
цикл1:
  mov dx, 0 ;НЕОБХОДИМО ДЕЛИТЬ НА BX.
  div bx ;DX:AX / 10 = AX:ЧАСТНОЕ DX:ОСТАТОК.
  push dx ;СОХРАНИТЬ ИЗВЛЕЧЕННУЮ ЦИФРУ НА ПОЗЖЕ.
  inc cx ;УВЕЛИЧЕНИЕ СЧЕТЧИКА ДЛЯ КАЖДОЙ ИЗВЛЕКАЕМОЙ ЦИФРЫ.
  cmp ax, 0 ; ЕСЛИ ЧИСЛО ЕСТЬ
  jne cycle1 ;НЕ НУЛЬ, LOOP.
;СЕЙЧАС ПОЛУЧИТЬ УДАЛЕННЫЕ ЦИФРЫ.
  мов си, смещение ул
цикл2:
  поп дх
  добавить dl, 48 ;ПРЕОБРАЗОВАТЬ ЦИФРУ В СИМВОЛ.
  мов [ си ], дл
  вкл си
  петлевой цикл2
  рет
конец
 

Далее ваш код с некоторыми изменениями, теперь он берет два параметра из стека и внутренне помещает их в переменные num1 и num2. Я не забочусь о параметрах для всей «печати»:

 proc display_interval
;ПОЛУЧИТЬ ПАРАМЕТРЫ.
    поп топор ;ОБРАТНЫЙ АДРЕС.
    всплывающее число2 ;ЧИСЛО2.
    всплывающее число1 ;ЧИСЛО1.
    нажать топор ;ВОЗВРАТИТЬ АДРЕС НАЗАД (НЕОБХОДИМО ДЛЯ "RET").
    распечатать сообщение4
интервал:
    ;ДОБАВИТЬ ТЕКУЩИЙ НОМЕР В СУММУ.
      mov ax, x ;AX = ТЕКУЩЕЕ ЧИСЛО.
      добавить к, топор
    ;ПРЕОБРАЗОВАТЬ ТЕКУЩЕЕ ЧИСЛО В СТРОКУ ДЛЯ ЕГО ОТОБРАЖЕНИЯ.
      коллировать доллары ;ЗАПОЛНИТЬ "STR" С '$'. НЕОБХОДИМО ДЛЯ ОТОБРАЖЕНИЯ.
      номер вызова2строка ;ПАРАМЕТР = AX. ВОЗВРАТ В ПЕРЕМЕННОЙ "STR".
    ;ЧИСЛО ОТОБРАЖЕНИЯ ПРЕОБРАЗОВАНО В СТРОКУ.
      мов а, 9mov dx, смещение ул
      через 21 час
    ;ОТОБРАЗИТЬ ЗНАК ПЛЮС.
      мов а, 9
      mov dx, смещение плюс
      через 21 час
    ;СЛЕДУЮЩИЙ НОМЕР ДЛЯ ОТОБРАЖЕНИЯ.
      вкл х
      ось перемещения, х
      cmp ось, у
      jbe интервал ;IF AX <= NUM2 THEN REPEAT.
    ;ОТОБРАЗИТЬ СУММУ.
    ;ОТОБРАЗИТЬ BACKSPACE (ДЛЯ УДАЛЕНИЯ ПОСЛЕДНЕГО ЗНАКА ПЛЮС). 
      распечатать обратно
    ;ОТОБРАЖАТЬ ЗНАК РАВНО.
      печатать равным
    ;ПРЕОБРАЗОВАТЬ СУММУ В СТРОКУ, ЧТОБЫ ОТОБРАЗИТЬ ЕЕ.
      коллировать доллары ;ЗАПОЛНИТЬ "STR" С '$'. НЕОБХОДИМО ДЛЯ ОТОБРАЖЕНИЯ.
      мов топор, к
      номер вызова2строка ;ПАРАМЕТР = AX. ВОЗВРАТ В ПЕРЕМЕННОЙ "STR".
    ;ЧИСЛО ОТОБРАЖЕНИЯ ПРЕОБРАЗОВАНО В СТРОКУ.
      мов а, 9mov dx, смещение ул
      через 21 час
      рет
конец
 

Процедура «display_interval» должна вызываться так:

 mov ax, 1
толкать топор ;ПЕРВЫЙ ПАРАМЕТР.
мов топор, 5
толкать топор ;ВТОРОЙ ПАРАМЕТР.
вызов display_interval
 

Добавить два числа на языке ассемблера · GitHub

; Программа для добавления двух чисел
раздел .текст
глобальный _start
_start:
; обрабатывает первый ввод
мов акс, 4; написать
мов ebx, 1; стандартный_выход
mov ecx, msg1; что написать
мов edx, msg1_len
интервал 0x80; sys_call
; выполнять вычисления
мов акс, 3; захватить данные с клавиатуры
мов ebx, 0;
mov ecx, число1;
мов эдкс, 5; помним наши 5 байт
интервал 0x80
; обрабатывает второй ввод
мов акс, 4; написать
мов ebx, 1; стандартный_выход
mov ecx, msg2; что написать
мов edx, msg2_len
интервал 0x80
; выполнять вычисления
мов акс, 3; захватить данные с клавиатуры
мов ebx, 0;
mov ecx, число2;
мов эдкс, 5; помним наши 5 байт
интервал 0x80
мов акс, 4
мов ebx, 1
мов ecx, сообщение
мов edx, msg_len
интервал 0x80
; записать окончательный вывод
mov eax, [число1]
sub eax, ‘0’ ;преобразование из ASCII в десятичное
mov ebx, [число2]
субэкс, ‘0’
добавить eax, ebx
добавить eax, ‘0’
мов [разрешение], eax
мов акс, 4
мов ebx, 1
мов экх, рез ; напишите результат
мов эдкс, 5
интервал 0x80
выход:
мов акс, 1
интервал 0x80
раздел . данные
msg1 db «Введите число 1: »
msg1_len equ $ — msg1
msg2 db «Введите число 2: »
msg2_len экв $ — msg2
msg db «Сумма: »
msg_len equ $ — msg
раздел .bss
num1 resb 5 ; разрешение 5 байт
число2 резб 5
рез ресб 5

Программа TASM для добавления двух 8-битных чисел

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

Цель:

Написать программа на ассемблере для добавления 8 бит.

Необходимое условие:

ТАСМ ассемблер

Алгоритм сложения 8 бит :

1)

Старт

2)

Инициализация сегмент данных через регистр AX в регистр DS.

3)

Дисплей сообщение типа «Введите первый номер»

4)

Читать первая цифра в регистре AL через клавиатуру          (например, АЛ=31ч)

5)

Звонок Процедура ввода для преобразования числа из шестнадцатеричного ASCII в обычное шестнадцатеричное номер. AL=01h

6)

Переместить содержимое регистра AL в BL. (BLß AL , поэтому BL=01h)

7)

Повернуть содержимое BL записывается на 4 позиции слева. (BL=10ч)

8)

Чтение вторая цифра в регистре AL через клавиатуру AL=35h

9)

Звонок Процедура ввода для преобразования числа из шестнадцатеричного ASCII в обычное шестнадцатеричное количество. AL=05h

10) 

Добавьте содержимое BL и AL сохранить результат в BL   (BLßBL+AL, поэтому BL=15h)

11) 

Отобразить сообщение как «Введите второе число»

12) 

Чтение первой цифры в регистре AL с помощью клавиатуры          AL=32h

13) 

Вызов процедуры ввода для создания число из шестнадцатеричного ASCII в обычное шестнадцатеричное число. AL=02h

14) 

Переместить содержимое регистра AL в кл. (CLß AL, поэтому CL=02h)

15) 

Повернуть содержимое CL зарегистрируйтесь на 4 позиции с левой стороны. (CL=20h)

16) 

  Прочитать вторую цифру в регистре AL через клавиатура (AL=33h)

17) 

Вызов процедуры ввода для создания число из шестнадцатеричного ASCII в обычное шестнадцатеричное число. AL=03h

18) 

Добавьте содержимое CL и AL сохранить результат в CL   (CLßCL+AL, поэтому CL=23h)

(В настоящее время оба числа принимаются как 15h и 23h)

19) 

Добавьте содержимое BL и CL и результат сохраняется в BL (например, ADD BL,CL, поэтому BL=38h)

20)

Сохранить результат сложения в какая-то временная переменная, скажем, temp из BL.

21) 

Маскируйте первый фрагмент с помощью И операция с номером F0h (И BL,F0h, поэтому BL=30h)

22) 

Процедура вывода вызова с BL зарегистрируйтесь, чтобы вернуть цифру в шестнадцатеричный диапазон ASCII (BL=33h)

23) 

Переместить содержимое BL в DL и вывести на экран

24) 

Переместить результат из временного переменная снова в BL (таким образом, BL=38h)

25) 

Маскируйте второй полубайт с помощью AND операция с номером 0Fh (И BL,0Fh, поэтому BL=08h)

26) 

Процедура вывода вызова с BL зарегистрируйтесь, чтобы вернуть цифру в шестнадцатеричный диапазон ASCII (BL = 38h)

27) 

Переместите содержимое BL в DL и вывести на экран

28) 

Стоп

Алгоритм для процедуры ввода: (для приема ввода от 0 до F)

1)

Сравнить содержимое AL с 41ч.

2)

Прыжок к шагу № 4, если установлен флаг переноса (цифра находится в диапазоне от 0 до 9, поэтому добавьте только 30ч)

3)

Sub 07h для регистра AL (если цифра находится в диапазоне от A до F, затем добавьте 30h и 7h оба)

4)

Суб 30ч в регистр AL

5)

 Возврат

Алгоритм для процедуры вывода:

1)

Сравнить содержимое BL с 0Ah

2)

Прыжок к шагу № 4, если установлен флаг переноса (цифра находится в диапазоне от 0 до 9, поэтому добавьте только 30ч)

3)

Добавить 07h в регистр BL (если цифра находится в диапазоне от A до F, затем добавьте 30h и 7h оба)

4)

Добавить 30 ч в регистр BL

5)

 Возврат


Пока маскирование F или f не чувствительно к регистру. Но в процедуре ввода номер 41h ​​есть рассматривается для сравнения, потому что 41h — это шестнадцатеричное значение ASCII для «A». На выходе процедура ‘0A’ считается, а не ‘a’ считается маленьким случаем a имеет 61h Шестнадцатеричное значение ASCII. Таким образом, эта процедура ввода и вывода применима только для заглавная буква от «А» до «F»

Программа TASM :

 Сегмент данных
 msg db 0dh,0ah,"Введите первое число: $"
 msg1 db 0dh,0ah,"Введите второе число: $"
 результат db 0dh,0ah,"Результат: $"
Данные заканчиваются
Сегмент кода
 предположим CS:Code,DS:Data
Начало:
 мов топор, данные ; Переместить данные в сегмент данных add8
 мов ДС, топор
 mov dx, смещение msg ; Показать содержимое переменной msg
 мов ах, 09h
 через 21 час
 мов ах,01ч ; Чтобы принять ввод и сохранить значение ASCII в al
 через 21 час
 суб ал, 30ч ; Принять 10-е место числа
 мов бл, ал
 ролик бл,4
 мов ах,01ч ; Чтобы принять ввод и сохранить значение ASCII в al
 через 21 час
 суб ал, 30ч ; Принять место единицы номера
 добавить бл, ал; Получите число, добавив разряд десятков и единиц
 mov dx, смещение msg1 ; Показать содержимое переменной msg1
 мов ах, 09час
 через 21 час
 мов ах,01ч ; Чтобы принять ввод и сохранить значение ASCII в al
 через 21 час
 суб ал, 30ч ; Принять 10-е место числа
 мов кл, ал
 роль кл,4
 мов ах,01ч ; Чтобы принять ввод и сохранить значение ASCII в al
 через 21 час
 суб ал, 30ч ; Принять место единицы номера
 добавить cl,al ; Получите число, добавив разряд десятков и единиц
 добавить бл, кл ; Добавьте два принятых номера
 mov dx, результат смещения ; Показать содержимое строки результата
 мов ах, 09h
 через 21 час
 мов кл, бл ; Сохраните значение результата
 и bl,0f0h ; Изолировать 10-е место результата
 рор бл,4
 вызов AsciiConv ; Преобразование в ASCII для отображения
 мов дл,бл ; Отображение числа/алфавита
 мов ах, 02h
 через 21 час
 мов бл,кл ; Получить исходный результат
 и bl,0fh ; Изолировать позицию юнита Результата
 вызов AsciiConv ; Преобразование в ASCII для отображения
 мов дл,бл ; Отображение числа/алфавита
 мов ах, 02h
 через 21 час
 мов ах,4ч ; Завершить программу
 через 21 час
 AsciiConv процедура ; Сравните с 0a, если это меньше, чем A, тогда нам нужно добавить только 30
  cmp bl,0ah ; Если он больше или равен 0a, то нам также нужно добавить 07
  Джей Си пропустить
  добавить бл,07ч
  пропустить: добавить bl,30h
  рет
  конец
Код заканчивается
конец начало
 

вывод:-

 C:\TASM\BIN>tasm add8.

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

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