Use saved searches to filter your results more quickly
Cancel Create saved search
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window.
Reload to refresh your session.
MASM. Арифметические и логические команды, команды переходов, команды работы с массивами и стеком, работа с математическим сопроцессором, нахождения функций с помощью математического сопроцессора, нахождение суммы ряда с помощью математического сопроцессора
apkuznetsov/masm-2017
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Switch branches/tags
Branches Tags
Could not load branches
Nothing to show
Could not load tags
Nothing to show
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
#6 Арифметические команды сложения ADD и ADC
Cancel Create
- Local
- Codespaces
HTTPS GitHub CLI
Use Git or checkout with SVN using the web URL.
Work fast with our official CLI. Learn more about the CLI.
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
Latest commit message
Commit time
README.md
Архитектура ЭВМ и ВС (2017)
Вычисление целочисленного выражения
- В программе необходимо реализовать функцию вычисления целочисленного выражения на встроенном ассемблере MASM в среде Microsoft Visual Studio на языке C++.
- Значения переменных передаются в качестве параметров функции.
- Результат выводить в консольном приложении (проект консольное приложение Win32).
- В программе реализовать ввод переменных из командной строки и вывод результата на экран.
- Все параметры функции 32 битные числа (знаковые и беззнаковые).
- Первые строки функции вычисления выражения заносят значения аргументов функции в соответствующие регистры.
- Где необходимо реализовать проверки вводимых данных и вычисления отдельных операций. Например, проверка деления на 0.
- В качестве комментария к каждой строке необходимо указать, какой промежуточный результат, в каком регистре формируется.
- По возможности использовать команды сдвига.
Вычисление условного целочисленного выражения
FASM. add, sub, mul, div, neg. Арифметика ассемблер. #3
- В программе необходимо реализовать функцию вычисления заданного условного целочисленного выражения, используя команды сравнения, условного и безусловного переходов на встроенном ассемблере.
- Результат X – целочисленный, возвращается из функции регистре eax.
- Значения переменных передаются в качестве параметров функции.
- В программе реализовать вывод результата на экран.
- Все параметры функции 32 битные числа.
- Проверку деления на 0 реализовать также на встроенном ассемблере.
- В качестве комментария к каждой строке необходимо указать, какой промежуточный результат, в каком регистре формируется.
- По возможности использовать команды сдвига.
Функция обработки массива
- В программе необходимо реализовать функцию обработки элементов массива используя команды сравнения, переходов и циклов на встроенном ассемблере.
- Результат – целочисленный, возвращается из функции регистре eax.
- Массив и количество элементов передаются в качестве параметров функции.
- В программе реализовать вывод результата на экран.
- В качестве комментария к каждой строке необходимо указать, какое действие выполняет команда относительно массива.
Функция вычисления заданного условного выражения
- В программе необходимо реализовать функцию вычисления заданного условного выражения на языке ассемблера с использованием команд арифметического сопроцессора.
- Значения переменных передаются в качестве параметров функции.
- В программе реализовать вывод результата на экран.
- Все параметры функции имеют тип double.
- Проверку деления на 0 реализовать также на встроенном ассемблере.
- В качестве комментария к каждой строке необходимо указать, какой промежуточный результат, в каком регистре формируется.
- В качестве комментария к строкам, содержащим команды сопроцессора необходимо указать состояние регистров сопроцессора.
- Результат можно возвращать из функции в вершине стека сопроцессора.
Функция вычисления значения некоторой элементарной функции
- В программе необходимо реализовать функцию определения значения некоторой элементарной функции, зависящей от аргумента на языке ассемблера с использованием команд арифметического сопроцессора.
- Значения переменных передаются в качестве параметров функции.
- Составить таблицу значений функции на указанном отрезке с шагом h = 0,1.
- Номер вычисления №, значения x и f(x) вывести для контроля на экран.
- Все параметры функции имеют тип double.
- Проверку деления на 0 реализовать также на встроенном ассемблере.
- В качестве комментария к каждой строке необходимо указать, какой промежуточный результат, в каком регистре формируется.
- В качестве комментария к строкам, содержащим команды сопроцессора необходимо указать состояние регистров сопроцессора.
- Результат можно возвращать из функции в вершине стека сопроцессора.
Функция вычисления значения некоторой элеменатрной функции y, зависящей от аргумента x
- В программе необходимо реализовать функцию определения значения некоторой элементарной функции y, зависящей от аргумента x на языке ассемблера с использованием команд арифметического сопроцессора.
- Функция вычисляется в виде суммы ряда. Вычисления прекращаются если |Sk+1 — Sk| N. Значение функции и количество итераций вывести для контроля на экран.
- Значение параметров x, eps и N передаются в качестве аргументов функции.
- В программе необходимо также реализовать функцию вычисления значения элементарной функции на основе аналитического выражения, также с использованием команд арифметического сопроцессора. Значение функции вывести для контроля на экран.
- Необходимо определить достигнутую погрешность, вычислив отклонение аналитического значения от значения, вычисленного с помощью ряда. Значение погрешности также вывести для контроля на экран.
- В качестве комментария к строкам, содержащим команды сопроцессора необходимо указать состояние регистров сопроцессора.
About
MASM. Арифметические и логические команды, команды переходов, команды работы с массивами и стеком, работа с математическим сопроцессором, нахождения функций с помощью математического сопроцессора, нахождение суммы ряда с помощью математического сопроцессора
Источник: github.com
7. Сложение и вычитание в i8086
Вычитание выполняется с помощью команды SUB . Результат также помещается на место первого операнда и опять же выставляются флаги. Единственная разница в том, что происходит вычитание, а не сложение.
На самом деле вычитание в процессоре реализовано с помощью сложения. Процессор меняет знак второго операнда на противоположный, а затем складывает два числа. Если вам необходимо в программе поменять знак числа на противоположный, можно использовать команду NEG. У этой команды всего один операнд.
sub si,dx ;SI = SI — DX neg ax ;AX = -AX
Инкремент и декремент
Очень часто в программах используется операция прибавления или вычитания единицы. Прибавление единицы называется инкрементом, а вычитание — декрементом. Для этих операций существуют специальные команды процессора: INC и DEC . Обратите внимание, что эти команды не изменяют значение флага CF .
Пример программы
Чтобы всё стало совсем понятно, напишем небольшую программу. Требуется вычислить значение формулы: e=a-(b+c-1)+(-d) . Все числа являются 8-битными целыми со знаком. Объявим их после кода и придумаем какие-нибудь значения. Вот что у меня получилось:
use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h mov al,[a] ;Загружаем значение a в AL mov ah,[b] ;Загружаем значение b в AH add ah,[c] ;AH = AH + c = b+c dec ah ;AH = AH — 1 = b+c-1 sub al,ah ;AL = AL — AH = a-(b+c-1) mov cl,[d] ;CL = d neg cl ;CL = -CL = -d add al,cl ;AL = AL + CL = a-(b+c-1)+(-d) mov [e],al ;Сохраняем результат в e mov ax,4C00h ; int 21h ;/ Завершение программы ;——————————————————- a db 2 b db 3 c db 5 d db -8 e db ?
Квадратные скобки означают, что операнд находится по адресу, указанному внутри этих скобок. Так как вместо имени переменной FASM подставляет её адрес, то такая запись позволяет прочитать или записать значение переменной.
Запустив программу в Turbo Debugger, можно посмотреть её выполнение по шагам. Значения переменных можно увидеть в окне дампа памяти. Для этого нужно кликнуть правой кнопкой в этом окне и выбрать в меню пункт Goto…. Переменные начинаются в памяти с адреса 011Fh (этот адрес в первой команде).
В этих байтах легко угадываются наши переменные:
Упражнение
Напишите программу для вычисления формулы k=m+1-(n-1-r) . Все числа 16-битные целые со знаком. Запустите в отладчике и проверьте правильность вычисления. Результаты можете выкладывать в комментариях ?
Источник: pro-prof.com
Арифметические операции над двоично-десятичными числами
Арифметические действия над неупакованными BCD-числами
Сложение неупакованных BCD-чисел
Рассмотрим два случая сложения.
6 = 0000 0110 + 3 = 0000 0011 = 9 = 0000 1001
Переноса из младшей тетрады в старшую нет. Результат правильный.
06 = 0000 0110 + 07 = 0000 0111 = 13 = 0000 1101
То есть мы получили уже не BCD-число. Результат неправильный. Правильный результат в неупакованном BCD-формате должен быть таким:
0000 0001 0000 0011 в двоичном представлении (или 13 в десятичном).
Проанализировав данную проблему при сложении BCD-чисел (и подобные проблемы при выполнении других арифметических действий) и возможные пути ее решения, разработчики системы команд микропроцессора решили не вводить специальные команды для работы с BCD-числами, а ввести несколько корректировочных команд.
Назначение этих команд — в корректировке результата работы обычных арифметических команд для случаев когда операнды в них являются BCD-числами.
В случае вычитания в примере 10 видно, что полученный результат нужно корректировать. Для коррекции операции сложения двух однозначных неупакованных BCD-чисел в системе команд микропроцессора существует специальная команда
aaa (ASCII Adjust for Addition) — коррекция результата сложения для представления в символьном виде.
- если это значение меньше 9, то флаг cf сбрасывается в 0 и осуществляется переход к следующей команде;
- если это значение больше 9, то выполняются следующие действия:
- к содержимому младшей тетрады al (но не к содержимому всего регистра!) прибавляется 6, тем самым значение десятичного результата корректируется в правильную сторону;
- флаг cf устанавливается в 1, тем самым фиксируется перенос в старший разряд, для того чтобы его можно было учесть в последующих действиях.
Листинг 8. Сложение неупакованных BCD-чисел ;prg_8_8.asm . .data lenequ 2 ;разрядность числа b db 1,7 ;неупакованное число 71 c db 4,5 ;неупакованное число 54 sum db 3 dup (0) .code main: ;точка входа в программу . xor bx,bx mov cx,len m1: mov al,b[bx] adс al,c[bx] aaa mov sum[bx],al inc bx loop m1 adc sum[bx],0 . exit:
- во-первых, такой порядок удовлетворяет общему принципу представления данных для микропроцессоров Intel;
- во-вторых, это очень удобно для поразрядной обработки неупакованных BCD-чисел, так как каждое из них занимает один байт.
Вычитание неупакованных BCD-чисел
Ситуация здесь вполне аналогична сложению. Рассмотрим те же случаи.
6 = 0000 0110 — 3 = 0000 0011 = 3 = 0000 0011
Как видим, заема из старшей тетрады нет. Результат верный и корректировки не требует.
6 = 0000 0110 — 7 = 0000 0111 = -1 = 1111 1111
Вычитание проводится по правилам двоичной арифметики. Поэтому результат не является BCD-числом.
Правильный результат в неупакованном BCD-формате должен быть 9 (0000 1001 в двоичной системе счисления). При этом предполагается заем из старшего разряда, как при обычной команде вычитания, то есть в случае с BCD числами фактически должно быть выполнено вычитание 16 – 7. Таким образом видно, что, как и в случае сложения, результат вычитания нужно корректировать. Для этого существует специальная команда:
aas (ASCII Adjust for Substraction) — коррекция результата вычитания для представления в символьном виде.
- если ее значение меньше 9, то флаг cf сбрасывается в 0 и управление передается следующей команде;
- если значение тетрады в al больше 9, то команда aas выполняет следующие действия:
- из содержимого младшей тетрады регистра al (заметьте — не из содержимого всего регистра) вычитает 6;
- обнуляет старшую тетраду регистра al;
- устанавливает флаг cf в 1, тем самым фиксируя воображаемый заем из старшего разряда.
Данная программа не требует особых пояснений, когда уменьшаемое больше вычитаемого. Поэтому обратите внимание на строку 24. С ее помощью мы предусматриваем случай, когда после вычитания старших цифр чисел был зафиксирован факт заема. Это говорит о том, что вычитаемое было больше уменьшаемого, в результате чего разность будет неправильной. Эту ситуацию нужно как-то обработать. С этой целью в строке 24 командой jc анализируется флаг cf. По результату этого анализа мы уходим на ветку программы, обозначенную меткой m2, где и будут выполняться некоторые действия.
Умножение неупакованных BCD-чисел
На примере сложения и вычитания неупакованных чисел стало понятно, что стандартных алгоритмов для выполнения этих действий над BCD-числами нет и программист должен сам, исходя из требований к своей программе, реализовать эти операции.
Реализация двух оставшихся операций — умножения и деления — еще более сложна. В системе команд микропроцессора присутствуют только средства для производства умножения и деления одноразрядных неупакованных BCD-чисел.
Для того чтобы умножать числа произвольной размерности, нужно реализовать процесс умножения самостоятельно, взяв за основу некоторый алгоритм умножения, например “в столбик”.
- поместить один из сомножителей в регистр al (как того требует команда mul);
- поместить второй операнд в регистр или память, отведя байт;
- перемножить сомножители командой mul (результат, как и положено, будет в ax);
- результат, конечно, получится в двоичном коде, поэтому его нужно скорректировать.
aam (ASCII Adjust for Multiplication) — коррекция результата умножения для представления в символьном виде.
- делит al на 10;
- результат деления записывается так: частное в al, остаток в ah.
Данную программу можно легко модифицировать для умножения BCD-чисел произвольной длины. Для этого достаточно представить алгоритм умножения “в столбик”. Листинг 10 можно использовать для получения частичных произведений в этом алгоритме. После их сложения со сдвигом получиться искомый результат.
Перед окончанием обсуждения команды aam необходимо отметить еще один вариант ее применения. Эту команду можно применять для преобразования двоичного числа в регистре al в неупакованное BCD-число, которое будет размещено в регистре ax: старшая цифра результата в ah, младшая — в al. Понятно, что двоичное число должно быть в диапазоне 0. 99.
Деление неупакованных BCD-чисел
Процесс выполнения операции деления двух неупакованных BCD-чисел несколько отличается от других, рассмотренных ранее, операций с ними. Здесь также требуются действия по коррекции, но они должны выполняться до основной операции, выполняющей непосредственно деление одного BCD-числа на другое BCD-число. Предварительно в регистре ax нужно получить две неупакованные BCD-цифры делимого. Это делает программист удобным для него способом. Далее нужно выдать команду aad:
aad (ASCII Adjust for Division) — коррекция деления для представления в символьном виде.
- умножить старшую цифру исходного BCD-числа в ax (содержимое ah) на 10;
- выполнить сложение ah + al, результат которого (двоичное число) занести в al;
- обнулить содержимое ah.
Листинг 11. Деление неупакованных BCD-чисел ;prg_8_11.asm . .data ;сегмент данных b db 1,7 ;неупакованное BCD-число 71 c db 4 ; ch db 2 dup (0) .code ;сегмент кода main: ;точка входа в программу . mov al,b aad ;коррекция перед делением div c ;в al BCD-частное, в ah BCD-остаток . exit:
Аналогично aam, команде aad можно найти и другое применение — использовать ее для перевода неупакованных BCD-чисел из диапазона 0. 99 в их двоичный эквивалент.
Для деления чисел большей разрядности, так же как и в случае умножения, нужно реализовывать свой алгоритм, например “в столбик”, либо найти более оптимальный путь.
Арифметические действия над упакованными BCD-числами
Как уже отмечалось выше, упакованные BCD-числа можно только складывать и вычитать. Для выполнения других действий над ними их нужно дополнительно преобразовывать либо в неупакованный формат, либо в двоичное представление. Из-за того, что упакованные BCD-числа представляют не слишком большой интерес, мы их рассмотрим кратко.
Сложение упакованных BCD-чисел
Вначале разберемся с сутью проблемы и попытаемся сложить два двузначных упакованных BCD-числа.
67 = 0110 0111 + 75 = 0111 0101 = 142 = 1101 1100 = 220
Как видим, в двоичном виде результат равен 1101 1100 (или 220 в десятичном представлении), что неверно. Это происходит по той причине, что микропроцессор не подозревает о существовании BCD-чисел и складывает их по правилам сложения двоичных чисел. На самом деле, результат в двоично-десятичном виде должен быть равен 0001 0100 0010 (или 142 в десятичном представлении).
Видно, что как и для неупакованных BCD-чисел, для упакованных BCD-чисел существует потребность как-то корректировать результаты арифметических операций.
Микропроцессор предоставляет для этого команду daa:
daa (Decimal Adjust for Addition) — коррекция результата сложения для представления в десятичном виде.
Команда daa преобразует содержимое регистра al в две упакованные десятичные цифры по алгоритму, приведенному в описании команды daa .
Получившаяся в результате сложения единица (если результат сложения больше 99) запоминается в флаге cf, тем самым учитывается перенос в старший разряд.
Листинг 12. Сложение упакованных BCD-чисел ;prg_8_12.asm . .data ;сегмент данных b db 17h ;упакованное число 17h c db 45h ;упакованное число 45 sumdb 2 dup (0) .code ;сегмент кода main: ;точка входа в программу . mov al,b add al,c daa jnc $+4 ;переход через команду, если результат mov sum+1,ah ;учет переноса при сложении (результат > 99) mov sum,al ;младшие упакованные цифры результата exit:
В приведенном примере все достаточно прозрачно, единственное, на что следует обратить внимание, — это описание упакованных BCD-чисел и порядок формирования результата. Результат формируется в соответствии с основным принципом работы микропроцессоров Intel: младший байт по младшему адресу.
Вычитание упакованных BCD-чисел
Аналогично сложению, микропроцессор рассматривает упакованные BCD-числа как двоичные и, соответственно, выполняет вычитание BCD-чисел как двоичных.
Выполним вычитание 67-75. Так как микропроцессор выполняет вычитание способом сложения, то и мы последуем этому: 67 = 0110 0111 + -75 = 1011 0101 = -8 = 0001 1100 = 28 .
Как видим, результат равен 28 в десятичной системе счисления, что является абсурдом. В двоично-десятичном коде результат должен быть равен 0000 1000 (или 8 в десятичной системе счисления).
При программировании вычитания упакованных BCD-чисел программист, как и при вычитании неупакованных BCD-чисел, должен сам осуществлять контроль за знаком. Это делается с помощью флага cf, который фиксирует заем из старших разрядов.
Само вычитание BCD-чисел осуществляется простой командой вычитания sub или sbb. Коррекция результата осуществляется командой das:
das (Decimal Adjust for Substraction) — коррекция результата вычитания для представления в десятичном виде.
Команда das преобразует содержимое регистра al в две упакованные десятичные цифры по алгоритму, приведенному в описании команды das .
Источник: www.i-assembler.ru