Використання макрокоманд та процедур. Ввід даних з клавіатури та вивід результату на екран

Інформація про навчальний заклад

ВУЗ:
Національний університет Львівська політехніка
Інститут:
Не вказано
Факультет:
КН
Кафедра:
Кафедра ЕОМ

Інформація про роботу

Рік:
2014
Тип роботи:
Лабораторна робота
Предмет:
Засоби системного програмування
Варіант:
7

Частина тексту файла (без зображень, графіків і формул):

Міністерство освіти і науки України Національний університет „Львівська політехніка” Кафедра ЕОМ Лабораторна робота №6 з курсу: «Засоби системного прграмування» на тему: «Використання макрокоманд та процедур. Ввід даних з клавіатури та вивід результату на екран» Варіант: №7 Вираз: X=A4/B2-C1*(D1+E2-K) K=717 МЕТА РОБОТИ: Набути навиків написання макрокоманд та процедур на Асемблері, освоїти способи передачі параметрів. Реалізувати ввід та вивід даних в десятковій системі числення. ТЕОРЕТИЧНІ ВІДОМОСТІ: Процедури та оператор CALL Процедура – це частина програми, яка може бути описана в довільному місці і містити дії над довільними даними. Процедура починається директивою PROC та завершується директивою ENDP. Кодовий сегмент може містити будь-яку кількість процедур, що розділяються директивами PROC і ENDP. Типова організація багато процедурної програми приведена нижче. Виклик процедури здійснюється командою CALL. Для повернення з процедури використовується команда RET.  Рис.1.Виклик процедур. Зверніть увагу на наступні особливості: - директиви PROC по мітках B10 і C10 мають операнд NEAR для вказівки того, що ці процедури знаходяться в поточному кодовому сегменті. У багатьох випадках, цей операнд опускається, тому що за замовчуванням асемблер приймає тип NEAR. - Кожна процедура має унікальне ім'я і містить власну директиву ENDP для вказівки кінця процедури. - Для передачі керування в процедурі BEGIN маються дві команди: CALL B10 і CALL C10. У результаті першої команди CALL керування передається процедурі B10 і починається її виконання. Досягши команди RET, керування повертається на команду безпосередньо наступну за CALL B10. Друга команда CALL діє аналогічно - передає керування в процедуру C10, виконує її команди і повертає керування по команді RET. - Команда RET завжди виконує повернення у вихідну програму. Програма BEGIN викликає процедури B10 і C10, що повертають керування назад у BEGIN. Для виконання самої програми BEGIN операційна система DOS викликає її, і наприкінці виконання команда RET повертає керування в DOS. Якщо процедура B10 не містить завершальної команди RET, то виконання команд продовжиться з B10 безпосередньо в процедурі C10. Якщо процедура C10 не містить команди RET, то будуть виконуватися команди, що йдуть за процедурою C10 з непередбаченим результатом. Використання процедур дає гарну можливість організувати логічну структуру програми. Крім того, операнд для команди CALL можуть мати значення, що виходять за межу від -128 до +127 байт. Технічно керування в процедуру типу NEAR може бути передане за допомогою команд переходу чи навіть звичайним порядковим кодуванням. Але в більшості випадків рекомендується використовувати команду CALL для передачі керування в процедуру і команду RET для повернення. Макрозасоби Для кожної закодованої команди асемблер генерує одну машинну команду. Але для кожного закодованого оператора компіляторної мови Pascal чи C генерується один чи більш (частіше багато) команд машинної мови. У цьому відношенні можна вважати, що компіляторна мова складається з макрооператорів. Асемблер також має макрозасоби, але макроси тут визначаються програмістом. Для цього задається ім'я макросу, директива MACRO, різні асемблерні команди, що повинний генерувати даний макрос і для завершення макровизначення - директива MEND. Потім у будь-якім місці програми, де необхідне виконання визначених у макрокоманді команд, досить закодувати ім'я макросу. У результаті асемблер згенерує необхідні команди. Використання макрокоманд дозволяє: - спростити і скоротити вихідний текст програми; - зробити програму більш зрозумілої; - зменшити кількість можливих помилок кодування. Прикладами макрокоманд можуть бути операції вводу-виводу, пов’язані з ініціалізацією регістрів і виконання переривань перетворення ASCII і війкового форматів даних, арифметичні операції над довгими полями, обробка рядкових даних, ділення за допомогою віднімання. Просте макровизначення Макровизначення повинне знаходитися до визначення сегмента. Розглянемо приклад простого макровизначення по імені INIT1, що ініціалізує сегментні регістри для EXE-програми:  Рис.2 просте макровизначення. Директива MACRO вказує асемблеру, що наступні команди до директиви ENDM є частиною макровизначення. Ім'я макрокоманди - INIT1, хоча тут можливі інші правильні унікальні асемблерні імена. Директива ENDM завершує макровизначення. Сім команд між директивами MACRO і ENDM складають тіло макровизначення. Імена, на які є посилання в макровизначенні, CSEG, DSEG і STACK повинні бути визначені де-небудь в іншому місці програми. Макрокоманда INIT1 може використовуватися в кодовому сегменті там, де необхідно ініціалізувати регістри. Коли асемблер аналізує команду INIT1, він спочатку переглядає таблицю мнемокодів і, не знайшовши там відповідного елемента, перевіряє макрокоманди. Оскільки програма містить визначення макрокоманди INIT1 асемблер підставляє тіло макровизначення, генеруючи необхідні команди - макророзширення. Програма використовує розглянуту макрокоманду тільки один раз, хоча є інші макрокоманди, призначені для будь-якої кількості застосувань і для таких макрокоманд асемблер генерує однакові макророзширення. Використання параметрів у макрокомандах У попередньому макровизначенні були потрібні фіксовані імена сегментів: CSEG, DSEG і STACK. Для того, щоб макрокоманда була більш гнучкою і могла приймати будь-як імена сегментів, визначимо ці імена, як формальні параметри: INIT2 MACRO CSNAME,DSNAME,SSNAME ; Формальні параметри ASSUME CS:CSNAME,DS:DSNAME,SC:SSNAME,ES:DSNAME PUSH DS SUB AX,AX PUSH AX MOV AX,DSNAME MOV DS,AX MOV ES,AX ENDM ;Кінець макровизначення Формальні параметри в макровизначенні вказують асемблеру на відповідність їхніх імен будь-яким аналогічним іменам у тілі макровизначення. Усі три формальних параметри CSNAME, DSNAME і SSNAME зустрічаються в директиві ASSUME, а параметр DSNAME ще й у наступній команді MOV. Формальні параметри можуть мати будь-які правильні асемблерні імена, що не обов'язково збігаються іменами в сегменті даних. Тепер при використанні макрокоманди INIT2 необхідно вказати як параметри дійсні імена трьох сегментів у відповідній послідовності. Наприклад, наступна макрокоманда містить три параметри, що відповідають формальним параметрам у вихідному макровизначенні: Макровизначення: INIT2 MACRO CSNAME, DSNAME, SSNAME (формальні параметри) Макрокоманда: INIT2 CSEG, DSEG, STACK (фактичні параметри) Оскільки асемблер уже визначив відповідність між формальними параметрами й операторами в макровизначенні, то тепер йому залишається підставити параметри макрокоманди в макророзширенні: Параметр 1: CSEG ставиться у відповідність з CSNAME у макровизначенні. Асемблер підставляє CSEG замість CSNAME у директиві ASSUME. Параметр 2: DSEG ставиться у відповідність з DSNAME у макровизначенні. Асемблер підставляє DSEG замість двох DSNAME: у директиві ASSUME і в команді MOV. Параметр 3: STACK ставиться у відповідність з SSNAME у макровизначенні. Асемблер підставляє STACK замість SSNAME у директиві ASSUME. Макровизначення з формальними параметрами і відповідні макророзширення приведені на рис.3. Формальний параметр може мати будь-яке правильне асемблерне ім'я (включаючи ім'я регістра, наприклад, CX), що у процесі асемблювання буде замінено на параметр макрокоманди. В одній макрокоманді може бути визначене будь-яка кількість формальних параметрів, розділених комами, аж до 120 стовпчика в рядку. Вивід на екран. 1. Використання групи функцій переривання DOS INT 21H, при цьому номер функції цього переривання вказується в регістрі AH: AH=02: Вивід символу. Для виводу символу на екран в поточну позицію курсору необхідно помістити ASCII код даного символу в pегістр DL. Коди табуляції, повернення каретки й кінця рядка діють звичайним чином. AH=09 Вивід на екран рядка в базовій версії DOS. Використання даної функції вимагає визначення текстового повідомлення в області даних, установки в регістрі AH значення 09 (виклик функциии DOS) і виклику переривання INT 21H. У процесі виконання операції кінець повідомлення визначається за ознакою закінчення рядка($). 2. Звертання до пристрою виводу(монітору), як до файлу. Це здійснюється шляхом використання функцій 40h переривання 21h При цьому у регістр CX заноситься кількість байт для виводу, а в регістр DX - адреса області виводу. У результаті успішного виконання операції виводу очищається прапорець переносу (CF) і в регістр AX встановлюється кількість виведених символів. При неуспішній операції встановлюється прапорець CF, а код помилки (в даному випадку 6) заноситься в регістр AX. Оскільки регістр AX може містити як довжину даних, так і код помилки, то єдиний спосіб визначити наявність помилки – перевірити прапорець CF. Процедура підготовки даних до виводу на екран Як видно з попереднього опису функцій друку на екран, єдино можливими даними для виводу є ASCII коди. Тому отримані в результаті обчислень шістнадцяткові значення слід перетворити у відповідні їм ASCII – коди, а вже потім застосувати одну з функцій 21h переривання. Очевидно, що для виводу шістнадцяткових значень будуть використані цифри від 0 до 9 та латинські букви A, B, C, D, E, F (або a,b,c,d,e,f). Відомо, що ASCII коди цих символів становлять: цифра ASCII-код десяткова ASCII-код шістнадцяткова  0 48 30  1 49 31  2 50 32  3 51 33  4 52 34  5 53 35  6 54 36  7 55 37  8 56 38  9 57 39   символ ASCII-код десяткова ASCII-код шістнадцяткова  A 65 41  B 66 42  C 67 43  D 68 44  E 69 45  F 70 46   символ ASCII-код десяткова ASCII-код шістнадцяткова  a 97 61  b 98 62  c 99 63  d 100 64  e 101 65  f 102 66   Отже: щоб отримати ASCII - код цифри слід до її значення додати 30h (або 48d); щоб отримати ASCII - код великої латинської літери до значення треба додати 37h (або 55d) (наприклад, для шістнадцяткового значення Сh, код повинен становити 43h, тобто Сh+37h, або в десятковому еквіваленті 12+55=67); щоб отримати ASCII - код малої латинської літери до значення треба додати 57h або 87d. (наприклад, для шістнадцяткового значення Dh, код малої літери повинен становити 64h, тобто Dh+57h, або в десятковому еквіваленті 13+87=100). При виводі на екран необхідно врахувати те, що в одному байті знаходиться дві шістнадцяткові цифри (або букви), тоді як для формування ASCII кодів використовується лише одна, тобто слід виділити спочатку старшу цифру а далі – молодшу (щоб відображення відповідало значенню). Для того щоб виділити старшу цифру в байті треба обнулити чотири молодші двійкові розряди (попередньо зберігши весь байт) а потім зсунути чотири старші на місце молодших. Далі, щоб виділити молодшу цифру, слід обнулити старші розряди. Якщо байт даних знаходиться в регістрі AL, то відповідні команди Асемблера будуть: mov ah,al and ah,0F0h shr ah,4 and al,0Fh тепер в регістрі AH знаходиться старша, а в регістрі AL – молодша цифра значення. Крім того, значення може міститися у двох, трьох і більше байтах. В такому випадку перевід треба починати з найстаршого байту (оскільки саме він буде виводитися першим) і зчитувати дані з пам’яті зменшуючи лічильник байтів. Якщо значення, яке буде виводитися розміщене в пам’яті не по одному байту, то слід використати оператор приведення типу PTR. Наприклад якщо в сегменті даних міститься директива A dw 2356h, то команда MOV AL, BYTE PTR A дозволить занести в однобайтний регістр AL значення 56h, а MOV AH, BYTE PTR A+1 занесе в регістр AH значення 23h Блок – схема алгоритму перетворення шістнадцяткового значення у ASCII – код  Як видно з блок-схеми, при утворенні ASCII – коду, до значення завжди треба додавати не менше ніж 30h. Тому для скорочення кількості необхідних операторів переходу, варто перетворити процедуру додавання наступним чином:  Для реалізації таких дій на Асемблері необхідно використовувати умовні переходи. До того ж, при перетворенні більше ніж одного байту, для скорочення кількості необхідних операторів варто використати оператор циклу, або створити підпрограму перетворення одного байту і викликати її необхідну кількість разів. Процедура переводу з шістнадцяткової в десяткову систему числення Для того щоб вивести на екран десятковий результат, маючи в пам’яті шістнадцяткове значення , треба перевести це значення в 10-ву систему числення, а потім до кожної десяткової цифри додати 30h, отримавши таким чином ASCII- код. Для переходу від системи числення з більшою основою до системи числення з меншою основою використовується ділення основу поки результат не буде менший за цю основу. Остачі, які будуть лежати в межах від 0 до 9 утворюють десяткове число. Наприклад, якщо треба перетворити шістнадцяткове число 965 в десяткову систему систему слід ділити його на 0А(h): 965(h) : 0А(h) = F0 (частка) 5(остача) F0(h) : 0А(h) = 18 (частка) 0(остача) 18(h) : 0А(h) = 2 (частка) 4(остача) Взявши остачі в порядку від останньої до першої і починаючи з останньої частки, маємо 2405 в десятковій системі числення. Блок – схема алгоритму перетворення шістнадцяткового значення в десяткове  Ввід з клавіатури 1. Використання групи функцій переривання DOS INT 21H, при цьому номер функції цього переривання вказується в регістрі AH: AH=01: Ввід символу з клавіатури з еховідображенням. Дана функція повертає значення в регістрі AL. Якщо вміст AL не дорівнює нулю, то воно являє собою стандартний ASCII- cимвол, наприклад, букву або цифру. Нульове значення в регістрі AL свідчить про те, що на клавіатурі була натиснута спеціальна функціональна клавіша, наприклад, Номе, F1 або PgUp. Для визначення скен-коду клавіш, необхідно повторити виклик функції Дана функція реагує на запит Ctrl/Break. AH=07: Прямий ввід із клавіатури без еховідображення. Дана функція працює аналогічно функції 01 із двома відмінностями: введений символ не відображається на екрані, тобто немає еха, і відсутня реакція на запит Ctrl/Break. AH=08: Ввід із клавіатури без еховідображення. Дана функція діє аналогічно функції 01 з однією відмінністю: введений символ не відображається на екрані. AH=0Ah - буферизований ввід стрічки з еховідображенням; Для використання даної функції область вводу вимагає наявності cписку параметрів, що містить поля, які необхідні при виконанні команди INT. По-перше, повинна бути визначена максимальна довжина тексту, що вводить. Це необхідно для попередження користувача звуковим сигналом, якщо набрано занадто довгий текст; символи, що перевищують максимальну довжину не приймаються. По-друге, у списку параметрів повинне бути певне поле, куди команда повертає дійсну довжину уведеного тексту в байтах. . По-третє, повинно бути виділено місце під введені символи. Для запиту на ввід необхідно помістити в регістр AH номер функції - 10 ( 0AH), у регістр DX завантажити адресу списку параметрів і виконати INT 21H. Команда INT очікує поки користувач не введе із клавіатури текст, перевіряючи при цьому, щоб кількість введених символів не перевищувало максимального значення, зазначеного в списку параметрів. Для вказівки кінця вводу користувач натискає клавішу Enter. Код цієї клавіші (0Dh) також заноситься в поле вводу. Таким чином, дійсна довжини тексту, що вводиться, є на одиницю менша від максимально передбаченої. AH=0Bh: Перевірка стану клавіатури. Дана функція повертає FFh у регістрі AL, якщо ввід із клавіатури можливий, у іншому випадку - 00. Цей засіб пов’язане з функціями 01, 07 і 08, які не очікують вводу з клавіатури. 2. Посимвольний ввід шляхом звертання до драйвера BIOS за допомогою переривання INT 16H Команда BIOS INT 16H виконує спеціальну операцію, яка відповідно до коду в регістрі AH забезпечує наступні три функції вводу клавіатури. AH=00: Читання символу. Дана функція поміщає в регістр AL черговий ASCII символ, введений із клавіатури, і встановлює скен код у регістрі AH.. Якщо на клавіатурі натиснута одна з спеціальних клавіш, наприклад, Номе або F1, то в регістр AL заноситься 00. Автоматичного еховідображення символу на екран не відбувається. AH=01: Визначення наявності введеного символу. Дана функція скидає прапорець нуля (ZF=0), якщо є символ для читання з клавіатури; черговий символ і скен-код будуть поміщені в регістри AL і AH, відповідно і даний елемент залишиться в буфері. AH=02: Визначення поточного стану клавіатури. 3. Звертання до клавіатури, як до файлу. Це здійснюється шляхом використання функцій 3Fh переривання 21h При цьому у регістр CX заноситься кількість байт для вводу, а в регістр DX - адреса області вводу. У результаті успішного виконання операції вводу очищається прапорець переносу (CF) і в регістр AX встановлюється дійсна кількість байт, що беруть участь в операції. При неуспішній операції встановлюється прапорець CF, а код помилки (в даному випадку 6) заноситься в регістр AX. Оскільки регістр AX може містити як довжину даних, так і код помилки, то єдиний спосіб визначити наявність помилки – перевірити прапорець CF, хоча помилки читання із клавіатури й виводу на екран - не часті. Після введеного тексту безпосередньо слідує символ повороту каретки (0Dh), що був введений, і символ кінця рядка (0Ah), що не був введений. Тому, максимальна кількість символів і розмір області вводу повинні передбачати місце для двох додаткових символів. Якщо буде введено менше символів ніж максимальне значення, то в пам'яті, після введених символів збережуться колишні значення. У результаті успішної операції буде очищений прапорець CF (що можна перевірити) і в регістрі AX буде встановлена кількість байт, введених із клавіатури(кількість введених символів +2). Процедура вводу даних з клавіатури Як видно з попереднього опису функцій вводу даних, єдине, що можна ввести з клавіатури це ASCII коди. Тому якщо дані, які вводяться повинні в подальшому використовуватися для арифметичних обчислень, отримані в результаті вводу символи, слід перетворити у відповідні їм шістнадцяткові значення, а вже потім виконувати обчислення виразів з ними. ASCII коди відрізняються від значень на певні константи: для цифр на 30h, для великих латинських літер – на 37h, для малих латинських літер – на 57h. Тому при вводі слід відняти ці значення від введених кодів, перевіривши що саме введено: цифра чи літера, а також проконтролювавши коректність вводу (наприклад чи не введена літера >F, або літера не латинського алфавіту, або символ що не є ні літерою ні цифрою). Далі слід врахувати, що ввід здійснюється від старшої цифри до молодшої і кожен ASCII – код займає один байт, хоча в ньому міститься лише одна шістнадцяткова цифра. Тому треба «ущільнити» введені дані, починаючи з останнього введеного символу і розмістити в пам’яті за принципом молодша адреса – молодший байт. В залежності від того яка функція вводу буде обрана, послідовність дій для перекодування буде різною. При посимвольному вводу (функція 01 переривання 21h ) кожен введений ASCII – код одразу перевіряється на коректність, віднімається константа і записується у тимчасову область пам’яті як шістнадцяткове значення у форматі один байт – одна цифра. Далі, з тимчасової області зчитується по два байти, починаючи з наймолодшого (тобто з останнього введеного). Старший з байтів зсувається на чотири двійкові розряди вліво і результат додається до молодшого, таким чином відбувається «ущільнення», тобто утворення коректного шістнадцяткового значення, яке записується в пам’ять (блок схема алгоритму наведена далі). При вводі рядка символів (функція 0Ah переривання 21h ) перевірка на коректність та віднімання константи відбуваються вже після закінчення вводу, а далі виконуються ті ж самі дії, що й при посимвольному вводі. Для того, щоб визначити чи належить введений символ до шістнадцяткової системи числення, ASCII – код повинен лежати в таких межах: 30h ≤ {код}≤ 39h , або 41h ≤ {код} ≤ 46h , або 61h ≤ {код} ≤ 46h. В першому випадку символ є цифрою, в другому - великою латинською літерою від А до F, в третьому - малою латинською літерою від а до f. Різниця між ASCII – кодом і значенням становить відповідно, 30h, 37h(30h+7h), 57h(30h+7h+20h). Таким чином для перевірки символу на належність до шістнадцяткової системи числення треба: від ASCII – коду відняти константу 30h;. якщо отримане значення буде менше за нуль, то символ точно не є ні цифрою ні буквою (помилка при вводі); якщо значення більше за нуль але менше за десять, то було введено цифру; якщо значення більше за десять, то від нього треба відняти 07h; якщо отриманий результат менший десяти, то введене значення не належить до шістнадцяткової системи числення; якщо результат не менший від десяти(0Ah) і не більший від п’ятнадцяти (0Fh), то було введено введену велику латинську літеру в діапазоні від А до F; якщо значення більше за десять, то від нього треба відняти 20h; якщо отриманий результат менший десяти, то введене значення не належить до шістнадцяткової системи числення; якщо результат не менший від десяти(0Ah) і не більший від п’ятнадцяти (0Fh), то було введено введену малу латинську літеру в діапазоні від А до F. Блок – схема алгоритму перетворення ASCII – коду в шістнадцяткове значення  Процедура переводу з десяткової в шістнадцяткову систему числення Якщо ввід здійснюється в десятковій системі числення, то значення повинні складатися лише з цифр від нуля до дев’яти. При цьому ASCII коди відрізняються від значень цифр на 30h. Тому для отримання значень достатньо від ASCII – коду відняти 30h, або просто обнулити старшу тетраду введеного байту за допомогою команди логічного множення («і»). Далі слід застосувати процедуру переводу з 10-ої в 16-ву систему і отримати остаточні значення, з якими можна обчислювати вирази. Для переходу від системи числення з меншою основою до системи числення з більшою основою використовується множення на меншу основу з відповідною вагою розрядів. Наприклад, якщо треба перетворити десяткове число 965 в шістнадцяткову систему слід: 5*0А0(h)+6*0А1(h)+9*0А2(h), тут 0А – основа десяткової системи (10), записана у вихідній, тобто 16-ій системі. Маємо, відповідно: 5*1(h)=5h; 6*А(h)=3С(h); 9*64(h)=384(h). Додавши отримані значення, отримуємо: 5(h)+3С(h)+384(h)=3C5(h) Отже якщо після вводу, в пам’яті містяться десяткові значення за принципом молодша адреса – старший розряд (бо ввід відбувається від старшої до молодшої цифри), то обробку треба починати з наймолодшої цифри, (тобто з найстаршої адреси) і продовжувати справа наліво. Блок – схема алгоритму перетворення десяткового значення в шістнадцяткове  ЗАВДАННЯ: 1. Створити *.exe програму, яка реалізовує обчислення, заданого варіантом виразу над даними, введеними в десятковій системі і результат виводить на екран в десятковій формі. Програма повинна складатися з трьох основних підпрограм: процедура вводу - забезпечує ввід даних з клавіатури в десятковій формі і їх перевід у двійкове значення ; процедура безпосередніх обчислень – здійснює всі необхідні арифметичні дії у двійковій системі; процедура виводу – забезпечує перевід війкового результату у десятковий формат та вивід на екран. Передача параметрів може здійснюватися довільним чином. Кожна з перерахованих процедур може містити довільну кількість додаткових підпрограм. Вхідні операнди А, В, С, D, E, F вважати беззнаковими і довжиною в байтах, згідно з індексу. К – константа, довжина якої визначається значенням(згідно варіанту). 2. Переконатися у правильності роботи кожної процедури зокрема та програми загалом. 3. Скласти звіт про виконану роботу з приведенням тексту програми та коментарів до неї. 4. Дати відповідь на контрольні запитання. КОД ПРОГРАМИ: ;X=A4/B2-C1*(D1+E2-K) ;K=717D=02CDh _mij_variant ;==================================================================== ;X=К-B(1)+C(2)/D(1)-E(1)*F(1) ;К=354690D=56982h _variant_priklady ;==================================================================== DOSSEG .8086 .MODEL SMALL ;==================================================================== 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 ;==================================================================== .STACK 100h .DATA K EQU 2CDh A dd 00h B dw 00h C db 00h D db 00h E dw 00h Temp1 dd 00h,00h ;chastka_AB Temp2 dw 00h ;suma_DE Temp3 dd 00h ;riznitza_SumiDE&K Temp4 dd 00h ;riznitza_SumiDE&K X dw 00h,00h ;riznitza_Kinzeve ;-------------------------------------------------------------------- X_Str db 10 dup (0) TempStr db 10 dup (0) TempBin dw 0,0 MaxLen dw 0 X_div2 dw 0,0 Y_div2 dw 0 ;-------------------------------------------------------------------- MESSG_X DB 13,10,'X=A4/B2-C1*(D1+E2-K) К=717 (02CDh)','$' 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_X1 DB 13,10,'X= ','$' erStr1 db 13,10,'Data not input_variable',13,10,'$' erStr2 db 13,10,'Incorrectly data ',13,10,'$' erStr2_1 db 13,10,'B =0 --> divide by zero ',13,10,'$' erStr3 db 13,10,'Data is too long ',13,10,'$' ;-------------------------------------------------------------------- Mult10 dw 1,0 my_z dw 0,0 ;==================================================================== .CODE Start: mov ax,@data mov ds,ax call input call calculation call output ;-------------------------------------------------------------------- mov ah,01 int 21h ;-------------------------------------------------------------------- mov ah,4Ch int 21h ;-------------------------------------------------------------------- input proc LEA DX,MESSG_X MOV AH,09 INT 21H ;-------------------------------------------------------------------- LEA DX,MESSG_A MOV AH,09 INT 21H mov di,offset A mov MaxLen,10 mov cx,MaxLen call input_variable ;-------------------------------------------------------------------- LEA DX,MESSG_B MOV AH,09 INT 21H mov di,offset B mov MaxLen,5 mov cx,MaxLen call input_variable ;-------------------------------------------------------------------- cmp B,0 jne dali mov ah,09 mov dx, offset erStr2_1 int 21h mov ah,4Ch int 21h ;-------------------------------------------------------------------- dali: LEA DX,MESSG_C MOV AH,09 INT 21H mov di,offset C mov MaxLen,3 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,5 mov cx,MaxLen call input_variable ;-------------------------------------------------------------------- ret input endp ;==================================================================== calculation proc xor ax,ax xor bx,bx xor cx,cx xor dx,dx ;-------------------------------------------------------------------- mov ax,word ptr A mov dx,word ptr [A+2] mov bx,B div bx mov Temp2,ax ;A4/B2 (4/2=2) ;-------------------------------------------------------------------- mov ax,word ptr D mov dx,E add ax,dx mov word ptr Temp1,ax ;D1+E2 (2+2=4) mov ax,0 adc ax,0 ;ax=ax+0+C mov word ptr [Temp1+2],ax ;-------------------------------------------------------------------- mov ax,word ptr Temp1 mov dx,K sub ax,dx mov word ptr Temp3,ax ;(D1+E2-K) (4-4=4) mov ax,word ptr [Temp1+2] mov dx,0 sbb ax,dx mov word ptr [Temp3+2],ax mov ax,0 sbb ax,0 ;ax=ax-0-C mov word ptr [Temp3+4],ax ;-------------------------------------------------------------------- xor dx,dx mov ax,word ptr Temp3 mul C mov word ptr Temp4,ax mov word ptr [Temp4+2],dx mov ax,word ptr [Temp3+2] mul C add ax,word ptr [Temp4+2] mov word ptr [Temp4+2],ax adc dx,0 mov word ptr [Temp4+4],dx ;C1*(D1+E2-K) (4*1=6) ;-------------------------------------------------------------------- clc mov ax,Temp2 mov dx,word ptr Temp4 sub ax,dx mov word ptr X,ax ;A4/B2-C1*(D1+E2-K) mov ax,0 mov dx,word ptr [Temp4+2] sbb ax,dx mov word ptr [X+2],ax mov ax,0 mov dx,word ptr [Temp4+4] sbb ax,dx mov word ptr [X+4],ax mov ax,0 sbb ax,0 mov word ptr [X+8],ax ;-------------------------------------------------------------------- ret calculation endp ;==================================================================== input_variable PROC mov si,0 In_00: mov ah,01 int 21h cmp al,0Dh je In_1 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 call Err1 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,0FFFFh ja In_Err jmp In_3 In_2_1: cmp MaxLen,5 jl In_2_2 cmp dx,00 ja In_Err cmp ah,0ffh ja In_Err jmp In_3 In_2_2: cmp ax,00FFh jbe In_3 In_Err: LEA DX,erSTR3 MOV AH,09 INT 21H mov ah,4Ch int 21h ;-------------------------------------------------------------------- In_3: mov [di],ax mov [di+2],dx mov TempBin,0 mov TempBin+2,0 mov Mult10,1 mov Mult10+2,0 ;-------------------------------------------------------------------- RET input_variable ENDP ;==================================================================== Err1 PROC PUBLIC Err1 LEA DX,erSTR1 MOV AH,09 INT 21H mov ah,4Ch int 21h RET Err1 ENDP ;==================================================================== CHECK_BYTE PROC PUBLIC CHECK_BYTE sub dl,30h cmp dl,00 jl ErS cmp dl,0Ah jl GO ErS: LEA DX,erSTR2 MOV AH,09 INT 21H mov ah,4Ch int 21h GO: RET CHECK_BYTE ENDP ;==================================================================== MY_DIV2 proc sub cx,cx sub bx,bx mov dx,X_div2+2 mov ax,X_div2 M2_D1: cmp dx,Y_div2 jb M2_D3 sub ax,Y_div2 sbb dx,00 add cx,01 adc bx,0
Антиботан аватар за замовчуванням

29.05.2014 21:05-

Коментарі

Ви не можете залишити коментар. Для цього, будь ласка, увійдіть або зареєструйтесь.

Ділись своїми роботами та отримуй миттєві бонуси!

Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!
Нічого не вибрано
0%

Оголошення від адміністратора

Антиботан аватар за замовчуванням

Подякувати Студентському архіву довільною сумою

Admin

26.02.2023 12:38

Дякуємо, що користуєтесь нашим архівом!