Cистемне програмування
ЛАБОРАТОРНА РОБОТА № 2.
Використання математичного співпроцесора.
Мета: познайомитися з принципами роботи математичного співпроцесора і використати його можливості для обчислення арифметичних виразів.
Обробка знакових даних
Числові поля можуть трактуватися як знакові, або як беззнакові. Це контролюється при написанні програми самостійно. Для беззнакових величин всі біти є бітами даних і замість обмеження +32767 регістр може містити числа до +65535. Для знакових величин лівий біт є знаковим. Команди ADD, SUB і т.д. не роблять різниці між знаковими і беззнаковими величинами, вони просто додають і віднімають біти, тому трактування результату повністю лежить на розробнику програми. У випадку складних обчислень над багатобайтними знаковими числами затрати на контроль над результатом можуть перевищити самі обчислення. Тому для таких випадків доцільніше використовувати можливості математичного співпроцесора.
Використання математичного співпроцесора
Математичний або арифметичний співпроцесор (FPU) призначений для виконання операцій над числами в форматі з плаваючою комою і довгими цілими числами. Він значно прискорює обрахунки, які пов’язані з дійсними числами. Співпроцесор може виконати як прості арифметичні операції (множення, додавання, віднімання, ділення), так і обраховувати значення різних функцій(косинус, синус, тангенс, котангенс).
Основна область застосування математичного співпроцесора – наукові обрахунки, машинна графіка, і звичайно ж ігри, які моделюють реальний світ, оскільки такі ігри, як правило, включають в себе і машинну графіку, та інженерні обрахунки.
Безпосереднє програмування арифметичного співпроцесора позволяє більш оптимально побудувати код програми і пришвидшити обрахунки. Багато засобів програмування дозволяють робити асемблерні вставки, які дають можливість напряму звертатись до співпроцесора. Це в свою чергу, дозволяє відмовитися від використання додаткових бібліотек, необхідних для роботи з дійсними числами. При цьому, відповідальність за коректність операндів і перевірку результатів у випадку безпосереднього програмування арифметичного співпроцесора, повністю покладається на програміста.
Зараз переважна більшість персональних комп’ютерів в якості центрального процесора використовують різні покоління процесора Pentium фірми Intel. Цей процесор має вбудований математичний співпроцесор.
Принципи роботи співпроцесора.
Математичний співпроцесор запускається центральним процесором. Після запуску він виконує всі обрахунки самостійно і паралельно з роботою центрального процесора. Якщо центральний процесор направляє наступну команду співпроцесору в той момент, коли співпроцесор ще не закінчив виконання попередньої команди, центральний процесор переводиться в стан очікування. Якщо ж співпроцесор не зайнятий, центральний процесор, направивши команду співпроцесору, продовжує свою роботу, не очікуючи завершення обрахунку. Послідовне розташування команд співпроцесора і центрального процесора в коді програми створюють ілюзію послідовного їх виконання. Простіше кажучи можлива така ситуація, що коли центральний процесор звернеться до комірки пам’яті, куди арифметичний співпроцесор повинен був записати результат своїх обчислень і якщо співпроцесор ще не закінчив обрахунки то результату там не буде. Однак є спеціальні засоби синхронізації (команда FWAIT).
Префікс команд та адресація операндів
Команди, які призначенні для виконання співпроцесором, записуються в програмі як звичайні машинні команди центрального процесора, але всі вони починаються з байта, який відповідає команді центрального процесора ESC. Зустрівши таку команду, процесор передає її співпроцесору, а сам продовжує виконання програми з наступної команди.
Асемблерна мнемоніка всіх команд співпроцесора починається з букви F, наприклад: FADD, FDIV, FSUB і так далі. Команди співпроцесора можуть адресувати операнди, аналогічно звичайним командам центрального процесора. Операндами можуть бути або дані, які розміщуються в основній пам’яті комп’ютера, або внутрішні регістри співпроцесора.
Для команд арифметичного співпроцесора можливі всі види адресації даних, які використовуються центральним процесором.
Формати даних
Математичний співпроцесор може обробляти дані в форматі з плаваючою комою і цілі числа.
Дійсні числа. В загальному вигляді дійсні числа в загальних обрахунках можна записати наступним чином:
(знак)(мантиса)*10(знак)(порядок)
Наприклад: -1.35*105 (мінус одна ціла тридцять п’ять сотих, помножені на десять в п’ятому степені).
Тут знак: мінус, мантиса: 1.35, порядок: 5. Порядок теж може мати знак.
Важливим є таке поняття, як нормалізоване представлення чисел: якщо ціла частина мантиси числа складається з однієї цифри, не рівної нулю, то число з плаваючою крапкою називається нормалізованим. Перевага використання нормалізованих чисел полягає в тому, що для фіксованої розрядної сітки числа (тобто для фіксованої кількості цифр в числі) нормалізовані числа мають найбільшу точність. Крім того, нормалізоване представлення виключає неоднозначність, яка може виникнути через те, що кожне число з плаваючою крапкою може бути представлене різними (ненормалізованими) способами (наприклад: 123.5678*10^5 = 12.35678*10^6 = 1.235678*10^7 = 0.1235678*10^8 ).
При програмуванні на мовах високого рівня зустрічається наступне представлення чисел з плаваючою крапкою:
(знак)(мантиса)E(знак)(порядок)
Наприклад, -5.35E-2 означає число -5.35*10-2 (мінус п’ять цілих тридцять п’ять сотих, помножені на десять в мінус другому ступені).
Арифметичний співпроцесор може працювати з дійсними числами в трьох форматах:
- одинарної точності (4 байти)
- подвійної точності (8 байт)
- розширеної точності (10 байт)
При будь-якому представленні. старший біт визначає знак дійсного числа: 0 - додатне число, 1 – від’ємне число. Всі числа, рівні по модулю, відрізняються лише цим бітом, оскільки для представлення від’ємних чисел доповняльний код не використовується, на відміну від центрального процесора.
Арифметичний співпроцесор працює з нормалізованими двійковими числами. Двійкове число з плаваючою крапкою називається нормалізованим, якщо ціла частина мантиси рівна 1. З метою розширення розрядної сітки, ця одиниця не зберігається у форматах одинарної і подвійної точності. У форматі з розширеною точністю зберігається і "зайвий" біт цілої частини нормалізованого числа. Основна причина використання для обчислень розширеної точності - оберігання програми від можливої втрати точності обчислень, пов’язаної з великими відмінностями в порядках чисел, що беруть участь в арифметичних операціях.
Поле порядку - це степінь числа 2, на який множиться мантиса, плюс зсув, рівний 127 для одинарної точності, 1023 - для подвійної точності і 16383 - для розширеної точності.
Для того, щоб визначити абсолютне значення числа з плаваючою крапкою, можна скористатися наступними формулами:
- Одинарна точність: 1.(цифри мантиси)*2Р-127
- Подвійна точність: 1.(цифри мантиси)* 2Р-1023
- Розширена точність: 1.(цифри мантиси)* 2Р-16383
Знак числа визначається старшим бітом.
Наприклад:
Маємо таке число представлено з одинарною точністю:
Для цього числа знаковий біт рівний 1 (від’ємне число), порядок рівний 126, мантиса - 11 (у двійковій системі числення).
Значення цього числа рівне:
1.11 * 2(126-127)= -1.75 * 2^-1 = -0,875
Цілі числа.Арифметичний співпроцесор разом з дійсними числами здатний обробляти і цілі числа. Він має команди, що виконують перетворення цілих чисел в дійсні і назад.
Можливий чотири формати цілих чисел:
- ціле число;
- коротке ціле число;
- довге ціле число;
-упаковане двійково-десяткове число.
Ціле число займає два байти. Його формат повністю відповідає формату, що використовується центральним процесором. Для представлення від’ємних чисел використовується доповняльний код.
Коротке ціле і довге ціле мають аналогічні формати, але займають, відповідно, 4 і 8 байт.
Упаковане двійково-десяткове число займає 10 байт. Це число містить 18 десяткових цифр, розташованих по дві в кожному байті. Знак упакованого BCD числа знаходиться в старшому біті найлівішого байта. Решта біт старшого байта повинна бути рівні 0.
Існують команди співпроцесора, які перетворюють числа у формат упакованих двійково-десяткових чисел з внутрішнього представлення в розширеному дійсному форматі. Якщо програма робить спробу перетворення в упакований формат ненормалізованих чисел, нечисел, нескінченності і т.ін., в результаті виходить невизначеність. Невизначеність в упакованому BCD форматі є числом, в якому два старші байти містять одиниці у всіх розрядах. Вміст решти восьми байтів довільний. При спробі використовувати таке упаковане число в операціях - фіксується помилка.
Регістри співпроцесора.
Арифметичний співпроцесор має наступну систему регістрів:
8 регістрів загального призначення для роботи з даними (R0–R7, кожний розміром 10 байт), до яких можна звертатися тільки як до елементів стеку (де ST(0) – його вершина);
регістр стану SR (два байта);
регістр управління CR (два байта);
регістр тегів TW (два байта);
регістр вказівника команди FIP (шість байтів);
регістр вказівника операнду команди FDIP (шість байтів).
Числові регістри.
Числові регістри, як правило, в технічній літературі позначаються ST0 - ST7.
Числові регістри використовуються за принципом стеку.
Регістр стану в полі ST містить номер числового регістра, що є вершиною стеку. При виконанні команд як операнди можуть виступати числові регістри. В цьому випадку номер вказаного в команді регістра додається до вмісту поля ST регістра стану і таким чином визначається регістр, що використовується. Більшість команд після виконання збільшують поле ST регістра стану, записуючи результати своєї роботи в стек числових регістрів.
Система команд математичного співпроцесора
Можливі три формати команд співпроцесора, аналогічні форматам команд центральних процесорів фірми Intel. Це команди зі звертанням до оперативної пам’яті, команди зі звертанням до одного з числових регістрів і команди без операндів, заданих явним чином.
Команди зі звертанням до пам’яті можуть займати від двох до чотирьох байт, залежно від способу адресації.
Всі асемблерні мнемоніки команд співпроцесора починаються з букви F, тому їх легко відрізнити від команд центрального процесора.
Команди співпроцесора можна розділити на декілька груп:
команди пересилки данихарифметичні командикоманди порівнянь чиселтрансцендентні команди
команди керування
Команди пересилки даних призначені для завантаження чисел з оперативної пам’яті в числові регістри, записи даних з числових регістрів в оперативну пам’ять, копіювання даних з одного числового регістра в іншій.
Арифметичні команди виконують такі операції, як додавання, віднімання, множення, ділення, знаходження квадратного кореня, знаходження часткового залишку, округлення і т.п.
Команди порівняння порівнюють дійсні і цілі числа, виконують аналіз чисел.
Трансцендентні команди призначені для обчислення різних тригонометричних, логарифмічних, показникових і гіперболічних функцій - sin, cos, tg і т.ін.
Команди керування забезпечують установку режиму роботи арифметичного співпроцесора, його скидання і ініціалізацію, перехід співпроцесора в захищений режим роботи і т.д.
Основні команди математичного співпроцесора
Команда
Функція
Операнд 1
Операнд 2
Результат
Команди пересилки даних
FLD
Завантажити відправник (змінна дійсного типу) до стеку (регістр ST(0))
відправник
–
ST(0)
FILD
Завантажити відправник (змінна цілого типу) до стеку (регістр ST(0))
відправник
–
ST(0)
FST
Копіювати значення зі стеку (регістр ST(0)) до приймача (змінна дійсного типу)
приймач
–
приймач
FSTP
Прочитати значення зі стеку (регістр ST(0)) до приймача (змінна дійсного типу)
приймач
–
приймач
FIST
Копіювати значення зі стеку (регістр ST(0)) до приймача (змінна цілого типу)
приймач
–
приймач
FISTP
Прочитати значення зі стеку (регістр ST(0)) до приймача (змінна цілого типу)
приймач
–
приймач
FXCH
Обмін значеннями регістрів ST(0) та відправника (інший регістр)
відправник
–
–
FCMOVxx
Група команд умовної пересилки даних
приймач
відправник
ST(0)
Група команд умовної пересилки даних FCMOVxx
Команда
Реальна умова
Умова для команди FCOM
FCMOVE
ZF = 1
Якщо рівні
FCMOVNE
ZF = 0
Якщо нерівні
FCMOVB
CF = 1
Якщо менше
FCMOVBE
CF = 1 та ZF = 1
Якщо менше або рівні
FCMOVNB
CF = 0
Якщо не менше
FCMOVNBE
CF = 0 та ZF = 0
Якщо не менше або рівні
Основні команди математичного співпроцесора
Команди управління FPU
FINIT
Ініціювання роботи математичного співпроцесора FPU
–
–
–
FSTCW
Копіювання вмісту регістру CR до приймача (змінна розміром 2 байта або регістр загального призначення)
приймач
–
змінна
FLDCW
Копіювання відправника (змінна розміром 2 байта) до регістру CR
відправник
–
CR
FSTSW
Копіювання вмісту регістру SR до приймача (змінна розміром 2 байта або регістр AX)
приймач
–
змінна або AX
Арифметичні команди математичного співпроцесора
Співпроцесор використовує шість основних типів арифметичних команд:
Fxxx
Перший операнд береться з вершини стека (джерело), другий - наступний елемент стека. Результат виконання команди записується в стек
Fxxx пам’ять
Джерело береться з пам’яті, приймачем є вершина стека ST(0). Покажчик стека ST не змінюється, команда дійсна тільки для операндів з одинарною і подвійною точністю
Fixxx пам’ять
Аналогічно попередньому типу команди, але операндами можуть бути 16- або 32-розрядні цілі числа
Fxxx ST, ST(i)
Для цього типу регістр ST(i) є джерелом, а ST(0) - верхівка стека - приймачем. Покажчик стека не змінюється
Fxxx ST(i), ST
Для цього типу регістр ST(0) є джерелом, а ST(i) - приймачем. Покажчик стека не змінюється
FXXXP ST(i), ST
Регістр ST(i) - приймач, регістр ST(0) - джерело. Після виконання команди джерело ST(0) витягується із стека
Рядок "xxx" може приймати наступні значення:
ADD - Додавання
SUB - Віднімання
SUBR - Зворотне віднімання, тобто операнди міняються місцями
MUL - Множення
DIV - Ділення
DIVR - Зворотне ділення, ділене і дільник міняються місцями
Окрім основних арифметичних команд є додаткові арифметичні команди:
FSQRT - Знаходження квадратного кореня
FSCALE – Масштабування на ступінь числа 2
FPREM - Обчислення часткової остачі
FRNDINT - Округлення до цілого
FXTRACT - Виділення порядку числа і мантиси
FABS – Знаходження абсолютного значення (модуля) числа
FCHS - Зміна знаку числа
Контрольні запитання:
1. Для чого використовується математичний співпроцесор?
2. Які формати даних може обробляти математичний співпроцесор?
3. Які числові регістри має співпроцесор?
4. Які регістри керування має співпроцесор?
5. Які групи команд має співпроцесор?
6. Які команди пересилки даних співпроцесора ви знаєте?
7. Які команди управління співпроцесора ви знаєте?
8. Які арифметичні команди FPU ви знаєте?
Література:
1.Р.Джордейн.Справочник програмиста персональных компъютеров типа ІBM PC XT и AT. - M."Финансы и статистика",1992,стор.13-31.
2.Л.О.Березко,В.В.Троценко. Особливості програмування в турбо-асемблері. -Киів,НМК ВО,1992.
3.Л.Дао. Программирование микропроцессора 8088.Пер.с англ.-М."Мир",1988.
4.П.Абель.Язык ассемблера для ІBM PC и программирования. Пер. з англ.-М.,"Высшая школа",1992.
ЗАВДАННЯ:
Створити *.exe програму, яка реалізовує обчислення, заданого варіантом виразу.Вхідні дані повинні вводитися з клавіатури, під час виконання програми в десятковому форматі зі знаком. Розмірність даних в байтах зберігати згідно варіанту.
Програма повинна складатися з двох модулів:головний модуль – створюється мовою С і має забезпечити ввід необхідних даних, виклик асемблерної процедури для обчислення виразу та вивід результату обчислень;модуль безпосередніх обчислень – здійснює всі необхідні арифметичні дії з використанням математичного співпроцесора;
Переконатися у правильності роботи кожного модуля зокрема та програми загалом.
Скласти звіт про виконану роботу з приведенням тексту програми та коментарів до неї.
Дати відповідь на контрольні запитання.
ВАРІАНТИ ЗАВДАННЯ
№
Вираз
K
1
X=A2+B2*C1-D2/E1+K
1254021
2
X=A4/B2+C3-D1*E1-K
202
3
X=K-B2+C2/D1-E1*F2
37788663
4
X=A1*(B2+C1)-D4/E2+K
45694
5
X=A2*B2-A2*C1-D4/E2+K
505
6
X=K+B2/C1-D2*F2-E1
6DD02316
7
X=A4/B2-C1*(D1+E2-K)
717
8
X=A4-B2+K-D2/E1+F1*B2
88
9
X=A1*B2-A1*C2+D2/(E1+K)
29
10
X=A4-B4/C2+K+E2*F1
2310
11
X=(A4-B3-K)*D1+E4/F2
311
12
X=K+B4/C2-D2*F2-E1
7055E0AC
13
X=A2/B1+C1*(D1+E2-K)
2513
14
X=A4-B1-K-D2/E1+F1*B1
614
15
X=A3+(B1*C2)-D4/E2+K
4569600F
16
X=A4/B2+C2-D1*E1+K
616
17
X=A4-K+C4/D2-E1*F1
1017
18
X=A1*(B2-C1)+D2/E1+K
56987018
19
X=A2*B2+A2*C1-D2/E1+K
4019
20
X=K+B4/C2-D1*F1-E2
18932020
21
X=A4/B2+C1*(D2 – E1+K)
21
22
X=K-B1-C1-D2/E1+F2*B1
45781022
23
X=A2*B2-C1+D4/E2+K
7AA02023
24
X=K-B2/C1+D3+E2*F2
74569024
25
X=(K-B2-C1)*D1+E4/F2
2B05025
26
X=A2+K+C2/D1-E1*F1
6C26
27
X=A2*B1+C4/(K-E1*F1)
A77627
28
X=K+B4/C2+D3-E2/F1
3FF28
29
X=K-B1*C1+D2-F2/E1
12A0C029
30
X=K+B3-D2/C1+E1*F2
25630
Приклад виконання.
Завдання: Написати програму, яка обчислює арифметичний вираз над знаковими даними, введеними в десятковій системі і результат виводить на екран в десятковій формі зі знаком.
Заданий вираз:
X=A4-B1+C2/D1-E1*F1
Оскільки дані, що вводяться повинні бути знаковими і зберігати заданий розмір, проаналізуємо які значення можуть бути введені, а отже і отримані в результаті обчислень.
Змінна
Max
Min
A (4 байти)
2147483647 (7FFFFFFF h)
-2147483648 (80000000 h)
B,D,E,F (1 байт)
127 (7F h)
-128 (80 h)
C (2 байти)
32767 (7FFF h)
-32768 (8000 h)
Для того, щоб уніфікувати ввід для від’ємних та додатних значень, обмежимось однаковими абсолютними значеннями, тобто А=±2147483647, B,D,E,F = ±127, C=±32767.
Текст програми, яка повністю реалізовує завдання, приведений нижче.Програма передбачає ввід знакових даних (процедура Input), тому слід перевіряти чи не є перший введений символ ознакою від’ємного числа («-») і чи не перевищує введена значення допустимих для даної розмірності меж. В першому випадку після коректного вводу, здійснюється утворення доповняльного коду. В другому випадку виводиться повідомлення про помилку і відбувається вихід з програми.
Далі, застосовуються можливості арифметичного співпроцесора для обчислень всіх арифметичних дій. Для цього в сегменті даних передбачаємо змінні, що будуть використовуватися для обчислень. Вони повинні бути 4 або 8 байтними(згідно форматів даних для співпроцесора). Для коректності представлення в програмі використовуються команди зміни розмірності – байту в слово: cbw , слова в подвійне слово cwd, подвійного слова в 8 байт: cdq. Далі виконуються послідовно всі арифметичні дії, з занесенням результатів у 8 байтові змінні. Оскільки, згідно завдання всі вхідні дані є цілими числами, для занесення значень у числові регістри співпроцесора використовується команда fild, а для запису у пам’ять - fistp. Для коректної емуляції цілочисельної арифметики, в програмі передбачається зміна режиму округлення результатів обчислень з округлення до найближчого числа (цей режим встановлюється при ініціалізації співпроцесора) на округлення у напрямку до нуля. Це здійснюється накладанням маски на значення у регістрі управління співпроцесора.
При формуванні та виводі остаточного результату (процедура Output), зважаючи на його знак відбувається утворення прямого коду для від’ємних значень та вивід на екран знаку «-» (мінус). Перевід з 16-ої в 10-ву систему відбувається для прямого коду. Оскільки загальний результат обчислень може займати більш ніж 4 байти, то для спрощення процедури переводу з 16-ої в 10-у систему числення застосовуються можливості математичного співпроцесора.
; main.asm головна програма
DOSSEG
EXTRN Input :FAR, Calculation :FAR, Output :FAR
PUBLIC erFlag
STACKSG SEGMENT PARA STACK 'Stack'
DW 127 DUP(0)
STACKSG ENDS
DATASG SEGMENT PARA PUBLIC 'Data'
erFlag DB 0
DATASG ENDS
CODESG SEGMENT PARA PUBLIC 'Code'
main:
ASSUME CS:CODESG,DS:DATASG,SS:STACKSG
MOV AX,DATASG
MOV DS,AX
CALL Input
cmp erFlag,0
jne A30
CALL Calculation
cmp erFlag,0
jne A30
CALL Output
cmp erFlag,0
jne A30
A30:
mov ah,4Ch
int 21h
CODESG ENDS
END main
;Input.asm модуль вводу даних
DOSSEG
EXTRN erFlag:BYTE
PUBLIC A0,A1,B,C,D,E,F
MY_MUL MACRO X,Y,Z
mov z,0
mov z+2,0
MOV AX,X
MUL Y
MOV Z,AX
MOV Z+2,DX
MOV AX,X+2
MUL Y
ADD Z+2,AX
mov ax,Z
mov dx,Z+2
ENDM
DATASG SEGMENT PARA PUBLIC 'Data'
A0 dw 00h
A1 dw 00h
B db 00h
C dw 00h
D db 00h
E db 00h
F db 00h
TempStr db 10 dup (0)
TempBin dw 0,0
MaxLen dw 0
FlagSign db 0
Mult10 dw 1,0
my_z dw 0,0
MESSG_X DB 13,10,'X= A-B+C/D-E*F','$'
MESSG_A DB 13,10,'A= ','$'
MESSG_B DB 13,10,'B= ','$'
MESSG_C DB 13,10,'C= ','$'
MESSG_D DB 13,10,'D= ','$'
MESSG_E DB 13,10,'E= ','$'
MESSG_F DB 13,10,'F= ','$'
erStr1 db 13,10,'Data not input_variable',13,10,'$'
erStr2 db 13,10,'Incorrectly data ',13,10,'$'
erStr3 db 13,10,'Data is too long ',13,10,'$'
DATASG ENDS
CODESG SEGMENT PARA PUBLIC 'CODE'
ASSUME DS:DATASG, CS:CODESG
input proc FAR
public Input
LEA DX,MESSG_X
MOV AH,09
INT 21H
LEA DX,MESSG_A
MOV AH,09
INT 21H
mov di,offset A0
mov MaxLen,10
mov cx,MaxLen
call input_variable
LEA DX,MESSG_B
MOV AH,09
INT 21H
mov di,offset B
mov MaxLen,3
mov cx,MaxLen
call input_variable
LEA DX,MESSG_C
MOV AH,09
INT 21H
mov di,offset C
mov MaxLen,5
mov cx,MaxLen
call input_variable
LEA DX,MESSG_D
MOV AH,09
INT 21H
mov di,offset D
mov MaxLen,3
mov cx,MaxLen
call input_variable
LEA DX,MESSG_E
MOV AH,09
INT 21H
mov di,offset E
mov MaxLen,3
mov cx,MaxLen
call input_variable
LEA DX,MESSG_F
MOV AH,09
INT 21H
mov di,offset F
mov MaxLen,3
mov cx,MaxLen
call input_variable
ret
input endp
input_variable PROC
mov si,0
In_00:mov ah,01
int 21h
cmp al,0Dh
je In_1
cmp al,'-'
jne In_0
mov FlagSign,1
jmp In_00
In_0: mov dl,al
call CHECK_BYTE
mov TempStr[si],dl
inc si
loop In_00
In_1: push si
dec si
cmp cx,MaxLen
jne In_2
LEA DX,erSTR1
MOV AH,09
INT 21H
mov erFlag,1
jmp In_5
In_2: mov bh,0
mov bl,TempStr[si]
MY_MUL Mult10,bx,my_z
add TempBin,ax
adc TempBin+2,dx
mov bh,0
mov bl,10
MY_MUL Mult10,bx,my_z
mov Mult10,ax
mov Mult10+2,dx
dec si
cmp si,0
jge In_2
mov ax,TempBin
mov dx,TempBin+2
pop si
cmp si,MaxLen
jl In_3
cmp MaxLen,10
jl In_2_1
js In_Err
cmp dx,7FFFh
ja In_Err
jmp In_3
In_2_1:cmp MaxLen,5
jl In_2_2
cmp dx,00
ja In_Err
cmp ah,7fh
ja In_Err
jmp In_3
In_2_2:cmp ax,007Fh
jbe In_3
In_Err:LEA DX,erSTR3
MOV AH,09
INT 21H
mov erFlag,1
jmp In_5
In_3:cmp FlagSign,1
jne In_4
mov bx,0
sub bx,ax
mov ax,bx
mov bx,0
sbb bx,dx
mov dx,bx
In_4: mov [di],ax
mov [di+2],dx
mov TempBin,0
mov TempBin+2,0
mov Mult10,1
mov Mult10+2,0
mov FlagSign,0
In_5: RET
input_variable ENDP
CHECK_BYTE PROC
sub dl,30h
cmp dl,00
jl ErS
cmp dl,0Ah
jl GO
ErS: LEA DX,erSTR2
MOV AH,09
INT 21H
GO: RET
CHECK_BYTE ENDP
CODESG ENDS
END
; calc.asm модуль обчислень
DOSSEG
EXTRN A0:WORD,A1:WORD,B:BYTE,C:WORD,D:BYTE,E:BYTE,F:BYTE
PUBLIC X,MESSG_Sign
DATASG SEGMENT PARA PUBLIC 'Data'
Afl dd 0
Bfl dd 0
Cfl dd 0
Dfl dd 0
Efl dd 0
Ffl dd 0
Temp1 dq 00h
Temp2 dq 00h
X dq 00h
RC dw 0
MESSG_Sign DB '$','$'
DATASG ENDS
CODESG SEGMENT PARA PUBLIC 'CODE'
ASSUME DS:DATASG, CS:CODESG
MOV AX,DATASG
MOV DS,AX
calculation proc Far
public calculation
mov ax,A0
mov dx,A1
mov word ptr Afl,ax
mov word ptr Afl+2,dx
mov al,B
cbw
cwd
mov word ptr Bfl,ax
mov word ptr Bfl+2,dx
mov ax,C
cwd
mov word ptr Cfl,ax
mov word ptr Cfl+2,dx
mov al,D
cbw
cwd
mov word ptr Dfl,ax
mov word ptr Dfl+2,dx
mov al,E
cbw
cwd
mov word ptr Efl,ax
mov word ptr Efl+2,dx
mov al,F
cbw
cwd
mov word ptr Ffl,ax
mov word ptr Ffl+2,dx
finit
fstcw RC
or RC,0c00h
fldcw RC
fild Afl
fild Bfl
fsub
fistp Temp1
fild Cfl
fild Dfl
fdiv
fistp Temp2
fild Temp1
fild Temp2
fadd
fistp Temp1
fild Efl
fild Ffl
fmulp
fistp Temp2
fild Temp1
fild Temp2
fsub
fistp X
mov cx,word ptr X+6
cmp cx,-1
jne M6
fild X
fchs
fistp X
mov MESSG_Sign,'-'
M6:
ret
calculation endp
CODESG ENDS
END
;Output.asm модуль виводу результату
DOSSEG
EXTRN X:QWORD, MESSG_Sign :BYTE
DATASG SEGMENT PARA PUBLIC 'Data'
X_Str db 12 dup (0)
ten dw 10
X1 dw 00h
MESSG_X1 DB 13,10,'X= ','$'
DATASG ENDS
CODESG SEGMENT PARA PUBLIC 'CODE'
ASSUME DS:DATASG, CS:CODESG
MOV AX,DATASG
MOV DS,AX
output PROC FAR
Public output
mov cx,10
mov di,0
O_1:
FFREE st(0)
FFREE st(1)
fild ten
fild X
fprem
fistp X1
mov dl,byte ptr X1
add dl,30h
mov X_Str[di],dl
inc di
fild X
FXCH ST(1)
fdiv
fRNDINT
fistp X
loop O_1
mov dx,offset MESSG_X1
mov ah,09
int 21h
mov dl,MESSG_Sign
mov ah,02
int 21h
inc di
mov cx,12
O_2:mov dl,X_Str[di]
mov ah,02h
int 21h
dec di
loop O_2
ret
output ENDP
CODESG ENDS
END