Міністерство освіти і науки України
Тернопільський національний економічний університет
Факультет комп’ютерних та інформаційних технологій
Кафедра спеціалізованих
комп’ютерних систем
КУРСОВА РОБОТА
з дисципліни “Системне програмування”
на тему:
“Програма розбору та обчислення простих математичних виразів”
Міністерство освіти і науки України
Тернопільський національний економічний університет
Факультет комп’ютерних та інформаційних технологій
Кафедра спеціалізовани комп’ютерних систем
Завдання на курсову роботу
Група: КСМ-21 Курс: другий
Студент:
“Програма розбору та обчислення простих математичних виразів”
Основні розділи курсової роботи:
РОЗДІЛ 1. Постановка задачі та опис алгоритму
РОЗДІЛ 2. Опис програми
РОЗДІЛ 3. Аналіз результатів та тестування програми
Рекомендована література:
1.Юров В. Assembler. – СПб. : Питер, 2001. – 624с.
2.Довідник з елементарної математики. Бевз Г.П. , Боголюбов О.М., Фільчаков П.Ф. та ін. – Київ : Наукова думка, 1975. – 655с.
3.Алкок Д. Язык паскаль иллюстрациях. – М.: Мир, 1991. – 192 с.
4.Пильщиков. Програмированиэ на языке ассемблера IBM PC. – M.: Диалог-миф. – 1994. – 206 с.
Дата видачі завдання
Дата представлення роботи на кафедру
Керівник роботи : доц. Сегін А.І.
ЗМІСТ
ВСТУП.........................................................................................................4
РОЗДІЛ 1. Постановка задачі та опис алгоритму............................6
РОЗДІЛ 2. Опис програми..................................................................8
РОЗДІЛ 3. Аналіз результатів та тестування програми...................11
ВИСНОВКИ...............................................................................................12
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ...............................................13
ДОДАТОК А..................................................................................................14
ВСТУП
Інформаційні системи та системи керування сьогодні складають велику частину фундаментальних та прикладних наукових дослідів. Хоча сучасні комп'ютерні технології в більшій мірі обслуговують потреби людини в технічній діяльності, ніж в їх природніх потребах, проте вони вже стали невідємною частиною повсякденного життя майже у всьому світі.
Сучасній людині важко уявити своє життя без електронно-обчислювальних машин (ЕОМ).
Спочатку XVII століття (1623р) вчений В. Шикард створив машину, здатну віднімати і додавати числа. Але першим арифмометром, здатним виконувати чотири арифметичні дії, став арифмометр відомого французького вченого і філософа Блеза Паскаль.В 1823р. – Чарльз Беббідж висунув ідею універсальної програмованої машини, яка мала пам’ять і працювала б на основі програми. В 40-х рр. було створено програмовану лічильну машину на основі електромагнітних реле. З 1943 р. почали конструюватись перші ЕОМ на основі електроних ламп. Поступово вони удосконалювались, з’явились нові покоління. З електронних ламп перейшли на транзистори ( II-ге покоління ), пізніше почали використовувати інтегровані схеми (III-те покоління ), великі інтегровані схеми( IV- те покоління ), великі інтегровані схеми високої інтеграції ( V-те покоління ). Сучасні комп’ютери ( мікропроцесорні ) беруть свій початок від того часу, коли фірмою Intel було випущено мікропроцесор (МП) і4004, він був 4-х розрядний, міг виконувати 4-ри арифметичні дії і спочатку використовувався тільки в мікрокалькуляторах. Майже всі сучасні комп’ютери базуються на базі 16-розрядного мікропроцесора і8086, який мав 1 Мбайт оперативної пам’яті. Зараз комп’ютери 32-розрядні з величезним об’ємом пам’яті і можуть виконувати безліч різноманітних операцій.
Сам асемблер колись був головною мовою програмування. Поступово ситуація змінилась. З’явились більш зручні способи спілкування з комп’тером. Але на відміну від інших мов асемблер не помер, юільше того він не може зробити це взагалі. Асемблер - це символічне представлення машинної мови. Всі процеси на машинному рівні проводяться тілбки командами машинної мови. По справжньому розв’язати проблеми, зв’зані з апаратурою, без знання асемблеру неможливо.Асемблер тісно пов’язаний з архітектурою мікропроцесора і з його удосконаленням і сам змінювався. Для кожного типу машин є свій асемблер.
Мікропроцесор може виконувати цілочисельні операції і операції з плаваючою точкою. Для цього в його архітектурі є два окремих блоки.
Пристрій для виконання цілочисельних операцій.
Пристрій для виконання операцій з плаваючою точкою.
Для більшості задач достатньо цілочисельних операцій. Призначення цієї курсової показати можливості цілосисельного блоку при розв’язуванні простих математичних виразів.
Вивчення особливостей розробки програм на Ассемблер є важливим компонентом в навчальному процесі підготовки майбутніх спеціалістів нашого напрямку. Саме тому глибоке знання теоретичних аспектів і хороше володіння практичними навиками є одним з головних передумов кваліфікованості по даному предмету.
РОЗДІЛ 1. Постановка задачі та опис алгоритму
В курсовій роботі необхідно реалізувати програму розбору і обчислення простих математичних виразів, що містили би будь-яку кількість дужок та основні чотири арифметичні операції :додавання і віднімання, множення , ділення .
Ми знаємо ,що дужки і порядок дій впливають на результат математичних виразів.
Якщо вираз містить дужки ,то ми його обчислюємо в такій послідовності:
дії виконуємо у дужках,враховуючи вищі та нижчі рівні пріоритетності;
дії без дужок в порядку згідно пріоритетності .
Тобто: 22+8-16/8-2+(6+9*2-14/7)+6=48.
6+9*2-14/7=6+18-2=22;
22+8-16/8-2+22=22+8-2-2+22=48.
У виразах зустрічаються і кілька дужок, тоді :
5+9/3*4+(6+(12+5-7)*2-25/5)+2*(4+2*5+7-12/6)=77.
12+5-7=12-2=10;
6+(12+5-7)*2-25/5=6+10*2-25/5=6+20-5=26-5=21;
4+2*5+7-12/6=4+10+7-2=14+5=19;
5+9/3*4+21+2*19=5+3*4+21+38=6+12+21+38=77.
Якщо у виразі є кілька дужок , то ми виконуємо дії у найвнутрішніших дужоках, як в кроці 1).
На результат виразу не тільки впливають дужки і їхній порядок , але й порядок виконання дій у них та поза ними.
Додавання і віднімання називають діями першого ступеня, множення і ділення – другого ступеня.
Ми знаємо ,що завжди при обчисленні математичних виразів виконуються дії спочатку вищого ступеня, а потім нижчого.Тобто, коли маємо у виразі і дії додавання , віднімання, і множення та ділення ,то ми виконуємо ці дії по порядку за рівнем їх пріоритетності, як вдужках, так і поза ними.
Якщо вираз без дужок і в ньому є дії тільки першого або тільки другого ступеня, то їх виконують у тому порядку, в якому вони написані, зліва направо.
Тобто: 42-25+62-55+5=17+62-55+5=79-55+5=24+5=29 або
108/12*5*3/9=9*5*3/9=45*3/9=135/9=15.
Дотримуючись цих правил я розробила такий алгоритм.
Алгоритм обчислення.
Перевірити вираз на правильність:
чи правильно збалансовані дужки;
чи немає зайвих символів;
якщо є помилка, то вивести повідомлення і перезапустити програму.
Визначити пріоритетну частину виразу:
якщо є дужки, то найбільший пріоритет має вираз у внутрішніх дужках ;
якщо дужок немає -береться увесь вираз.
Обчислити пріоритетну частину виразу:
виконати по порядку всі дії множення і ділення;
виконати по порядку всі дії додавання і віднімання.
На місце обчислюваного виразу у початковий вираз поставити результат.
Якщо у виразі залишилось більше одного числа, то перейти до пункту 2. Алгоритм закінчиться , коли виконаються усі обчислення.
РОЗДІЛ 2. Опис програми
Ця програма виконує обчислення математичних виразів. Вираз може містити всі 4 основні арифметичні дії і будь-яку кількість відкритих дужок. Вираз не повинен містити більше ніж 18 чисел. Проте програму легко можна модифікувати для будь якої довжини виразу. Якщо необхідно задати від'ємне число, то воно вводиться в дужках, відповідно, якщо результат від'ємний, то він виводиться в дужках. Після введення виразу потрібно натиснути клавішу Enter. Після цього програма виведе знак дорівнює і результат обчислення.
Приклад.
2+4/4*(-3)=(-1)
При використанні дії ділення результат може бути неправильний, оскільки при обчисленні не враховується залишок від ділення.
Для асемблювання і компонування програми я використав такі команди:
tasm /t MyCalc.asm
tlink /x MyCalc.obj
/t -придушення повідомлень при успішному асемблюванні
/x - не створювати MAP - файлу
Далі описана послідовність дій і основні процедури, які виконує програма в процесі виконання.
1. Очищує екран за допомогою макросу clearscr.
2. Bвикликається процедура InExp. Вводиться вираз. Після введення його з клавіатури, процедура перевіряє його на правильність відкриття і закриття дужок та на відсутність зайвих символів, доповнює кожну цифру спереду нулями до 10 цифр в числі.
Процедури.
EnterExp - ввід виразу з клавіатури.
lengstr - визначає довжину стрічки, викликається за допомогою макросу LenStr вираз, довжина, змінна для результату.
TestExpr - перевірити на зайві символи, викликається макросом TstExp вираз, довжина. Повертає ax=0, якщо вираз правильний, ax=2 якщо у виразі зайві символи. При помилці виконання процедури InExpression завершується.
TestingBrackets - перевірка на збалансованість дужок. Викликається макросом TestBracket вираз, довжина. Повертає в ax=0, якщо дужки збалансовані і ах=1, якщо незбалансовані. При помилці виконання процедури InExpression завершується.
2. Якщо ax не дорівнює нулю, то припинити обчислення і викликати процедуру обробки помилок ErrorProc, яка виводить повідомлення про помилку. Обчислення завершується.
4. Визначається довжина стрічки за допомогою процедури lengstr.
5. Процедура InTmpExpression копіює вираз, а якщо є дужки, то копіюється вираз у внутрішніх дужках, у змінну tmpexpression. Процедура викликається макросом MovePrior звідки, куди, довжина виразу, змінна куди занесеться адрес відкритої дужки, змінна для адресу закритої дужки.
6. Процедура Calculation обчислює вираз в tmpexpression. Шукає і виконує спочатку по порядку дії множення і ділення, а потім додавання і віднімання.
Процедури.
InOp - заносить в змінні a та b числа до і після знаку. Викликається макросом Operands адрес знаку, змінна для першого числа, змінна для другого, довжина числа.
TestOp - перевірити чи в операнд не занесено зайвих символів. Викликається макросом TstOp. Повертає в aх=3, якщо є помилка і ах=0, якщо нема. При помилці процедура Calculation обчислення припиняє.
Operation - визначити яку дію потрібно виконати і виконати її.
AddBCDp - додавання BCD- чисел, викликається макросом AddBCD операнд 1, операнд 2, довжина операнду. Результат повертається в першому операнді.
SubBCDp - віднімання BCD - чисел. Виклик SubBCD операнд 1, операнд 2, довжина операнду.
MulBCDp - множення. Виклик MulBCD операнд 1, операнд 2, довжина операндів.
DivBCDp - ділення. Виклик DivBCD операнд 1, операнд 2. довжина операндів.
ShiftInTmpExpr - ставить на місце двох операндів результат дії над ними.
7. Якщо ax не дорівнює нулю, то припинити обчислення і викликати процедуру обробки помилок ErrorProc, яка виводить повідомлення про помилку, після чого програма знову чекає вводу виразу.
8. Процедура ShiftInExpr вставляє, на місце виразу що обчислювався, в початковий вираз результат обчислення.
9. Перевіряється чи усе обчислено, якщо ні то повернутись до пункту 4.
10.Процедура Dysplay виводить результат обчислення.
РОЗДІЛ 3. Аналіз результатів та тестування програми
Після вводу виразу програма виводить результат після знаку дорівнює. Проаналізуймо кілька виразів.
1. 5-(4+2)=(-1)
Отже, обчислено правильно і програма зробила такі дії: спочатку обчислила в дужках, далі від 5 відняла 6.
2. 8+13-15-44+3+6=(-29)
Результат правильний, програма виконує дії однакового пріоритету по порядку.
3. 7+9*3+((4*4)-4)=2
Проаналізуймо як обчислено цей вираз:
1) 4*4=16 залишилось 7+9*3+(16-4)
2) 16-4=12 залишилось 7+9*3+12
3) 9*3=27 залишилось 7+27+12
4) 7+27+12=46 Результат 2
Отже спочатку обчислено вираз у внутрішніх дужках (1), далі у дужках, що залишились (2), виконало дію множення, оскільки вона має вищий пріоритет за дії додавання (3), виконало додавання(4).
Усі умови обчислення математичних виразів виконуються.
Далі приведено приклади неправильного вводу виразу і реагування на них програми.
4. (22/2-(4+5-3)
Error in brackets!
5. 6+-3*20
Error in expression (not right symbol)!
6. 2+7+j
There is illegal symbol in expression!
В 4-му виразі незбалансовані дужки, в 5-му після знаку "+" слідує "-", в 6-му на місці числа стоїть символ "j".
ВИСНОВКИ
Я набув значний досвід у написанні програм за допомогою мови програмування асемблер.
Людина здавна прагнула позбутись рутинних дій пов’язаних із виконанням певних послідовностей дій у арифметиці. І хоч моя програма не досконала, але це мій перший крок до створення подібних програм. Саме із складання таких програм в минулому все і почалося. Досвід здобутий при її реалізації дозволить мені в майбутньому займатися програмуванням більш прикладних задач.
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ
Юров В. Assembler. – СПб. : Питер, 2001. – 624с.
Довідник з елементарної математики. Бевз Г.П. , Боголюбов О.М., Фільчаков П.Ф. та ін. – Київ : Наукова думка, 1975. – 655с.
Алкок Д. Язык паскаль иллюстрациях. – М.: Мир, 1991. – 192 с.
Пильщиков. Програмированиэ на языке ассемблера IBM PC. – M.: Диалог-миф. – 1994. – 206 с.
ДОДАТОК А. Текст програми
;Макроси для обчислення математичного виразу
.286
TstExp macro string, len ;перевiрити на зайвi символи вираз
lea si, string ; в si-зміщення string
mov cx, len ;в cx-довжина стрічки
call TestExpr
endm
TstBracket macro string, len ;провiрка на правильнiсть вiдкриття i закриття дужок
;результат в ах
mov si, offset string
mov cx, len
call TestingBrackets
endm
TstOp macro string, len ; перевіряє чи в операнд не занесено зайвих символів
lea si, string
mov cx, len
call Test, Op
endm
GetSymbol macro string,symbol,len ;заповнює стрічку заданими символами
push ax
push cx
push di
cld
mov cx, len
lea di, string
mov al, symbol
rep stos string ; записати string в al cx раз
pop di
pop cx
pop ax
endm
strlen macro string,len,lenstring ;повернення довжини виразу
;"пробiл" - закiнчення стрiчки
mov cx, len ; в cx максимальна довжина
lea si, string ; в si – адрес string
call lengstr ; виклик процедури lengstr
mov lenstring, bx
endm
clrscr macro ;макрос очистки екрану
push ax
mov ah, 0 ; ah ф-ція BIOS встановлення відео режиму
mov al, 2 ; режим 2- текстовий
int 10h ; встановлення режиму очистки екрану
pop ax
endm
MovePrior macro StringS,StringD,len,Open,Close ;перемiщення прiоритетної частини виразу з StringS в StringD
;в Open занесеться адрес вiдкритої дужки
;в Close адрес закритої дужки
lea si, StringS ; в si адрес срічки StringS
lea di, StringD ; в di адрес срічки StringD
mov cx, len
call InTmpExpression ; Процедура InTmpExpression копіює вираз, а якщо є дужки, то ;копіюється вираз у внутрішніх дужках, у змінну tmpexpression. Процедура викликається макросом MovePrior ;звідки, куди, довжина виразу, змінна куди занесеться адрес відкритої дужки, змінна для адресу закритої дужки.
mov Open, ax
mov Close, dx
endm
Operands macro rbx, op1, op2, len
push di
push si
push bx
mov bx, rbx ; адрес знаку
lea di,op1 ; адрес для першого (лівого) операнду
lea si,op2 ; адрес для другого (правого) операнду
call InOperands
pop bx
pop si
pop di
endm
; Макроси для органiзацiї арифметичних дiй
InitReg macro mem1, mem2, len ;макрос для iнiцiалiзацi• адресних регiстрiв
mov di, len-1+offset mem1 ; адрес для першого операнду
mov si, len-1+offset mem2 ; адрес для другого операнду
mov cx, len ;довжина рядка до операнду
endm
AddBCD macro mem1,mem2,len ;додавання BCD-чисел
;результат помiщаїтся в перший операнд
InitReg mem1,mem2,len ; в si –адрес першого операнду , di-другого , cx-довжина
call AddBCDp
endm
SubBCD MACRO mem1,mem2,len ;вiднiмання BCD-чисел
;результат помiщаїтся в перший операнд
InitReg mem1,mem2,len ; в si –адрес першого операнду , di-другого , cx-довжина
call SubBCDp
endm
MulBCD macro mem1,mem2,len ;множення BCD-чисел
;результат:
;результат молодша частина помiщаїтся в перший варiант,
;старша - у другий операнд
Init mem1,mem2,len
call MulBCDp
endm
DivBCD macro mem1,mem2,len ;дiлення BCD-чисел
;результат:
;цiле помiщаїтся в перший операнд,
;остача - у другий операнд
mov di,offset mem1
mov si,offset mem2
mov cx,len
call DivBCDp
endm
OutBCD macro mem,len ;вивiд BCD-чисел на екран в поточну позицiю
mov si,offset mem
mov cx,len
call OutBCDp
endm
data segment ;для операцi• множення i дiлення потрiбен буфер
;розмiр буфера не менше 3*SIZE,
;де SISE-розмiр числа
buffer db 512 dup(?)
minus db 0
a db "0000000000"
b db "0000000000"
string db 200 dup(' ')
expression db 200 dup(' '),13,10,'$'
tmpexpression db 200 dup(" "),13,10,'$'
results db 200 dup(" "),13,10,'$'
counter db 0
len_str dw 200
len_tmpexpr dw 0
res_si dw 0
OpenBracket dw 0
CloseBracket dw 0
ErrorBrackets db "Error in brackets!",13,10,'$'
ErrorExpression db "There is illegal symbol in expression!",13,10,'$'
ErrorOperand db "Error in expression (not right symbol)!",13,10,'$'
data ends
code segment
assume cs:code,ds:data,es:data
; Процедури для здiйснення арифметичних дiй
AddBCDp proc
;процедура додавання BCD-чисел
pushа ax ;збережем використовуванi регiстри в стек
std ;починаїм з молодших розрядiв в прапорці DF (з права на ліво)
clc ;обнулити значення переносу прапорця CF
_add_:
lodsb ;вiзьмемо чергову цифру в AL , SI зменшим на 1, бо DF=1
adc al,[di] ;додамо з врахуванням переносу
aaa ;перетворимо в формат BCD-чисел
stosb ;збережемо результат в SI
loop _add_
pop cx ;вiдновим регiстри
pop si
pop di
pop ax
ret
endp
SubBCDp proc ;процедура віднімання BCD-чисел
push ax ;збережем використовуванi регiстри
push di
push si
push cx
std ;починаїм з молодших розрядiв
clc ;обнулити значення переносу
_sub_:
lodsb ;вiзюмемо чергову цифру
sbb [di],al ;вiднiмемо з врахуванням переносу
mov al, [di]
aas ;перетворимо в формат BCD-чисел
stosb ;збережемо результат
loop _sub_
pop cx ;вiдновим регiстри
pop si
pop di
pop ax
ret
endp
MulBCDp proc ;процедура множення BCD-чисел
push ax ;збережем використовуванi регiстри
push bx
push di
push si
push cx
std ;починаїм з молодших розрядiв
mov bx, offset buffer
mov dh, cl ;запам'ятаїмо початковий стан лiчильника (початкову довжину операнда)
push bx ; заповнемо буфер результату нулями
shl cx, 1 ;потрiбнийрозмiр 2*len ; при множенні n-розрядних чисел, результат має довжину 2n ;(максимум)
xor al, al ;символ-заповнювач = 0
_null_:
mov [bx], al ; заповнюєм буфер нулями
inc bx ; bx= bx+1
loop _null_
mov cl, dh ; відновлюєм cl
pop bx
;множення будем проводити стовпчиком
;цикл по всiм цифрам першого операнду
_mul_o_:
xor dl,dl ;обнулим значення переносу
push cx
push bx ;збережемо деякi регiстри
push si
mov cl,dh ;вiдновимо початкове значення лiчильника
;цикл по всiм цифрам другого операнда
_mul_i_:
lodsb ;вiзьмем чергову цифру
mul byte ptr [di] ;перемножим
aam ;коррекцiя результату в BCD
add al, dl ;врахуєм перенос
aaa ;корекція для додавання в BCD
add al, [bx] ;додамо до результату
;попереднього множення
aaa ;корекція для додавання в BCD
mov dl, ah ;запам'ятаєм значення переносу
xor ah,ah
mov [bx],al ;збережем результат
inc bx ; bx= bx+1
loop _mul_i_
mov [bx],dl
pop si ;вiдновим регiстри
pop bx
inc bx ; bx= bx+1
dec di ;перейдемо до наступно•
;цифри друго операнду
pop cx
loop _mul_o_
mov cl, dh ;вiдновим початкове
;значення лiчильника
sub bx, cx ;вiднiмемо вiд bx молодшу
;частину результату
add di, cx
;занесем результат (мол. част.) в перший операнд
_move_l_:
mov al,[bx]
inc bx
stosb
loop _move_l_
mov cl, dh
mov di, si
;занесем результат (ст. част.) в другий операнд
_move_h_:
mov al, [bx]
inc bx
stosb
loop _move_h_
pop cx ;вiдновимо регiстри
pop si
pop di
pop bx
pop ax
ret
endp
SubInvBCDp proc ;допомiжна процедура для операциї дiлення
;виконуї виклик процедури вiднiмання
;без початкової iнiцiалiзацiї
push si
push di
add si,cx
dec si
add di,cx
dec di
call SubBCDp
pop di
pop si
ret
ENDP
CоmpareBCDp proc ;процедура вiднiмання BCD-чисел
;CF=0, якщо [si]>[di], iнакше CF=1
push ax
push di
push si
push cx
cld ; DF=0, зліва на право
_cmp_:
lodsb
cmp al,[di]
jl _less_ ; якщо менше
jg _greater_ ; якщо більше
inc di
loop _cmp_
_less_:
stc ; CF =1
jc _cmp_q_
_greater_:
clc ; CF=0
_cmp_q_:
pop cx
pop si
pop di
pop ax
ret
endp
PrepForDiv proc ;процедура iнiцiалiзацiї буфера
;для операциї дiлення
cld ; DF=0 , зліва на право
;0,[di] -> buffer (перший операнд в буфер)
push di
push si
push di
pop si ; si = di
mov di, offset buffer ; в di адрес буфера
xor al, al ; al=0
push cx
stosb ; в al помістити по адресу si
rep movsb ; копіювання стрічки [SI] в [DI] довжиною CX
;0,[si] -> buffer (другий операнд в буфер)
pop cx
stosb
pop si
push cx
;для початку знайдемо першу значиму цифру
_find_:
lodsb ; в AL [SI]
dec cx
cmp al,0
je _find_
dec si
inc cx
mov dx,cx
rep movsb
pop cx
push cx
; 0,0..0 -> buffer (очистити мiсце для результату в буферi)
xor al,al
rep stosb
;переназначение регiстрiв
mov di,offset buffer
pop cx
mov si,di
inc cx
add si,cx
pop bx
ret
endp
DivBCDp proc
;процедура дiлення BCD-чисел
push ax ;збережемо використовуванi регiстри
push bx
push di
push si
push cx
push di
call PrepForDiv ;пiдготовим буфер
xor ax,ax ;в al - чергова цифра результату
;в ah - кiлькiсть цифр в результатi
call CоmpareBCDp
jnc _next_1_
_div_:
call CompareBCDp
jnc _next_
inc al
call SubInvBCDp
jmp _div_
_next_:
mov [bx],al ;збережемо чергову цифру
inc bx ;зменшим порядок чисельника
_next_1_:
inc di
dec cx
xor al,al
inc ah
cmp cx,dx ;порiвняїмо порядки чисельника и знаменника
jne _div_
dec ah
pop di
pop cx
push cx
;пересилаїм результат з буфера в операнд
mov si,di
add di,cx
push cx
mov cl,ah
add si,cx
dec si
dec di
std
rep movsb
pop cx
sub cl,ah
xor al,al
rep stosb
pop cx
pop si
push si
push cx
mov di,si
mov si,offset buffer
inc si
cld
rep movsb
pop cx ;вiдновимо регiстри
pop si
pop di
pop bx
pop ax
ret
endp
OutBCDp proc ;процедура вивода BCD-чисел на екран
mov ah,06h ; ф-ція DOS виводу символа на екран
cld ; DL=0 зліва на право
_out_:
lodsb ; з[SI] вAL
or al,30h ; перетворення символа в BCD формат
mov dl,al
int 21h ; виклик DOS
loop _out_
mov dl,0dh ; =13 (-перейти на новий рядок)
int 21h
mov dl,0ah ; =10
int 21h
ret
endp
; Процедури для обчислення математичних виразiв
;
InExpr proc
;Введення виразу з клавiатури
; запис його в ASCII-форматi в змiнну expression з доповненими нулями
; на виходi ax=0 - успiшне виконання процедури
; ax!=0 - час виконання виникла помилка
call EnterExpression ;введення виразу в string
LenStr string,200,len_str ;визначити довжину
TestExpression string,len_str ;перевiрка на зайвий символ
cmp ax,0 ;якщо ї зайвий символ
jne ErrorEnd ; то завершити процедуру
TestBracket string,len_str ;перевiрка дужок на правильнiсть
cmp ax,0 ;якщо ї зайвий символ
jne ErrorEnd ; то завершити процедуру
;переносимо цифри в змiнну a
;поки не зустрiнеться символ
lea dx,expression ;в dx адрес де формувати вираз
mov si,0 ;si використ. для перемiщення по string
mov cx,len_str ;в cx довжжина введено• стрiчки
inc cx
inc cx
mov bx,0
new:
mov di,0
ScanString:
mov al,string[si] ;Занести ASCII код символа в al
cmp al,39h ;Якщо
ja IsChar ; в al не цифра
cmp al,30h ;то