Міністерство освіти і науки, молоді та спорту України
Тернопільський національний економічний університет
Факультет комп’ютерних інформаційних технологій
Кафедра спеціалізованих
комп’ютерних систем
Курсова робота
з дисципліни “Системне програмування”
на тему:
“Програма розбору та обчислення простих математичних виразів”
Міністерство освіти і науки, молоді та спорту України
Тернопільский національний економічний університет
Факультет комп’ютерних інформаційних технологій
Кафедра спеціалізованих комп’ютерних систем
Завдання на курсову роботу
Група: СКС-21 Курс: другий
Студент: Груб’як Тарас Володимирович
“Тема курсової роботи”
Програма розбору та обчислення простих математичних виразів
Основні розділи:
Розділ 1. Аналіз технологічного завдання та методів його вирішення.
Розділ 2. Опис методики та алгоритм вирішення завдання.
Розділ 3. Аналіз результатів та тестування програми.
Рекомендована література:
1. Александр Крупнік «Ассемблер. Самоучитель»
2. Том Сван «Изучение языка ассемблера»
3. Зубков Сергей Владимирович «Assembler для Dos, Windows и Unix»
Дата видачі завдання "____"_______________201__р.
Дата представлення
роботи на кафедру "____"_______________201__р.
Керівник роботи: к.т.н., доц. Сегін А.І.
ЗМІСТ
Вступ..............................................................................................................4
РОЗДІЛ 1.Аналіз технічного завдання та методів його вирішення....5
РОЗДІЛ 2. Опис методики та алгоритму вирішення завдання............7
РОЗДІЛ 3. Опис програми та аналіз отриманих результатів...............9
3.2. Опис процедур і макросів......................................................................9
3.2. Аналіз отриманих результатів..............................................................10
Висновки........................................................................................................14
Список використаних джерел......................................................................15
Додаток А......................................................................................................16
ВСТУП
Програміст мислить за допомогою людської мови і живе у світі об'єктивної реальності, що його оточує, а комп'ютер - машина, що виконує інструкції, записані цим програмістом за допомогою мови програмування. Програма, яка повинна виконуватися, записана в машинних кодах, тобто машинною мовою. Машинна мова передбачає запис інструкцій та операндів у вигляді послідовностей нулів та одиниць. Машинна мова є мовою низького рівня. Програма в машинних кодах являє собою послідовність команд, які процесор може сприйняти і виконати безпосередньо. Кожний тип машин має свою машинну мову. Машинний код, написаний для однієї машини, не може бути виконаний на іншій без використання спеціального програмного забезпечення.
Німецький інженер Конрад Цузе був першим, хто успішно здійснив ідею створення обчислювальної машини на основі двійкової системи числення. У 1936 році він почав конструювати обчислювальний апарат, що працює в двійковій системі числення, що згодом був названий Zuse. Громіздкі статистичні обчислення для здійснення складних інженерних розрахунків повинні були стати автоматизованими, що було дотепер неможливо. Машина Цузе стала першим вичислювальним автоматом із програмним керуванням і вважається першим комп'ютером. Це програмне керування було написано на низькому рівні.
Ассемблер - мова програмування, в якій ми задаємо конкретно команди, які звертаються до машини, на відміну від мов програмування високого рівня. І хоча зараз є багато мов програмування високого рівня, які дещо простіші в написаннях програм, асемблер так і далі продовжують використовувати.
В даній курсовій роботі необхідно розробити на Ассемблері програму розбору та обчислення простих математичних виразів. Тобто, написана програма повинна розпізнати дужки в виразі, і в математичній послідовності обчислити вираз. А якщо вираз записано не правильно, програма повинна видати повідомлення про помилку.
РОЗДІЛ 1.
Аналіз технічного завдання та методів його вирішення
Основне завдання в даній курсовій роботі полягає в створенні програми, яка розбирає і обчислює прості математичні вирази, які б містили велику кількість дужок і прості арифметичні операції. Програма повинна виконувати ці обчислення за всіма математичними правилами, за правилами розкриття дужок, за правилами обчислення.
Коли обчислюються якісь математичні вирази потрібно дивитись на дужки і на самі дії. Тобто враховувати те, що спочатку виконуються обчислення в дужках. Самі перші обчислення виконуються в внутрішніх дужках, тобто потрібно враховувати рівень пріоритетності. Якщо в виразі декілька дужок однакового рівня пріоритетності, то обчислення в них відбувається по порядку. На прикладі показано як відбувається обчислення із врахуванням дужок.
Обчисленя цього виразу можна поділити на рівні:
( (6+4)-(2+6))+((7+2)*(6+5))*2 =202
10 8 9 11
2 99
101
Але під час обчислення потрібно враховувати не тільки дужки але й арифметичні дії. Тобто, так само як і з дужками, потрібно враховувати пріоритетність дій.
Коли розраховується вираз в якого лише додавання і віднімання, і не містить дужок, то ці арифметичні дії виконуються по порядку.
Наприклад :
5+2+4-6+5-2+3-4+2-2-3=4
В даному випадку ми просто виконуємо додавання і віднімання чисел попорядку зліва направо.
Коли розраховується вираз в якого лише множення і ділення, розрахунок відбувається аналогічно попередньому прикладу, тобто розрахунок виконується в попорядку зліва направо.
В наступному випадку коли змішані арифметичні дії додавання, відніманя, множення, ділення і немає дужок то першими виконуються множення і ділення, а потім додавання і віднімання.
І коли йдуть обчислення виразу який містить дужки і чотири арифметичні операції, то першими виконуються дії ті, що в дужках, не зважаючи чи то додавання, чи то множення, а потім виконуються дії за описаним вище.
РОЗДІЛ 2.
Опис методики та алгоритму вирішення завдання
Дана програма призначена для обчислення простих математичних виразів, тобто виконує такі математичні дії як, додавання, віднімання, множення і ділення. Також ця програма обчислює математичні вирази, якщо вони містять дужки. При неправильному введенні виразу, це може бути не правильно введені дії, чи не збалансовані дужки, програма виводить повідомлення про ту чи іншу помилку. Після введення виразу натиснувши enter програма виводить в тому самому рядку знак рівності і результат обчислення. Якщо, наприклад, число від’ємне то воно вводится і виводиться в дужках.
Ця програма була реалізована за таким алгоритмом:
1. Перевірка на правильність введеного виразу.
Після введення виразу, він заноситься в деяку змінну, після чого відбувається його перевірка. Спочатку перевіряється чи є зайві символи, перевіряється на правильність збалансованих дужок, а потім перевіряється чи правильно введені операнди. Якщо є якісь помилки, то програма виводить повідомлення про ту чи іншу помилку.
2. Визначення пріоритетної частини.
Після того, як не було виявлено жодної помилки, програма визначає кількість символів в змінній: якщо там одне число, то воно зразу виводиться, а коли там цілий вираз, програма визначає пріоритетну частину. Якщо є дужки, то пріоритетною частиною будуть самі внутрішні дужки.
3.Обчислення пріоритетної частини.
Визначивши пріоритетну частину, програма обчилює її, враховуючи те , що першими виконуються множення і ділення, а потім додаваня і віднімання, після чого результат заноситься в змінну на місце обчислюваного виразу( на місце обчислюваної пріоритетної частини виразу). І знов програма визначає кількість символів в змінній: якщо одне число, то воно виводиться, в іншому випадку програма повертається до пункуту 2, тобто визначає пріоритетну частину, і так цикл буде продовжуватись, поки не буде в змінній одне число.
4. Виведення результату.
Коли визначивши кількість символів в змінній, їх кількість буде рівна одиниці, результат буде виведено.
Блок-схема алгоритму показана в Додатку В.
РОЗДІЛ 3.
Опис програми та аналіз отриманих результатів
3.1. Опис процедур і макросів
В цій програмі я використовував багато процедур і макросів.
Однією з основних процедур програми є процедура Wwedennja. Завдяки їй відбувається введення виразу, після чого, процедура перевіряє його на правильність відкриття і закриття дужок та на відсутність зайвих символів, доповнює кожну цифру спереду нулями до 10 цифр в числі. Ця процедура містить багато підпроцедур:
EnterExp - ввід виразу з клавіатури.
lengstr - визначає довжину стрічки, викликається за допомогою макросу dovjuna вираз, довжина, змінна для результату.
Testsumvol - перевірити на зайві символи, викликається макросом Testsumvolr. В ax заноситься 0, якщо вираз правильний, ax=2 якщо у виразі зайві символи. При помилці виконання процедури Wwedennja завершується.
TestdujkuT - перевірка на збалансованість дужок. Викликається макросом Testdujku. ax=0, якщо дужки збалансовані і ах=1, якщо незбалансовані. При помилці виконання процедури Wwedennja завершується.
Якщо ax не дорівнює нулю, то припинити обчислення і викликати процедуру обробки помилок ErrorProc, яка виводить повідомлення про помилку.
lengstr – процедура призначена для визначення довжини стрічки.
Процедура InTmpExpression копіює вираз, а якщо є дужки, то копіюється вираз у внутрішніх дужках, у змінну tmpexpression. Процедура викликається макросом InTmpExpr
Процедура Kalkul обчислює вираз в tmpexpression. Шукає і виконує спочатку по порядку дії множення і ділення, а потім додавання і віднімання.
Testdiii - перевірити чи в операнд не занесено зайвих символів. Викликається макросом Testdii. Заносить в aх=3, якщо є помилка і ах=0, якщо нема. При помилці процедура Kalkul обчислення припиняє.
Operation - визначити яку дію потрібно виконати і виконати її.
AddBCDp - додавання BCD- чисел, викликається макросом
AddBCD операнд 1, операнд 2, довжина операнду. Результат повертається в першому операнді.
SubBCDp - віднімання BCD - чисел. Виклик SubBCD операнд 1, операнд2, довжина операнду.
MulBCDp - множення. Виклик MulBCD операнд 1, операнд 2, довжина операндів.
DivBCDp - ділення. Виклик DivBCD операнд 1, операнд 2. довжина операндів.
newrezultat – вставляє в expression результат на місце обчислюваного виразу.
wuwid – ця процедура виводить результат обчислення.
o4ustka –процедура очищення екрану.
3.2. Аналіз отриманих результатів
Зроблена програма працює за алгоритмом. Обчислює прості математичні вирази з дужками.
Можна проаналізувати декілька виразів обчислених програмою:
5+7+8-6=14 - результат правильний. В цьому випадку обчислення здійснювалося попорядку, оскільки всі дії однакового пріоритету (рис. 1)
Рис.1 Простий вираз
Розглянемо вираз з дужками:
4+(8-2)=10 - Знаючи алгоритм програми можна розібрати як було здійснено це обчислення. Спочатку була виконана дія в дужках 8-2=6, а потім 4+6=10 (рис.2)
Рис.2 Вираз з дужками
Тепер візьмемо дещо складніший вираз (рис.3)
50-(2*(1+4)-2)*3=26 - обчислення здійснювалися в такому порядку:
1) 1+4=5
2) 2*5=10
3) 10-2=8
4) 8*3=24
5) 50-24=26
Рис.3 Складний вираз
Ми проаналізували обчислення виразів і побачили як вони виконуються, тепер подивимось які будуть виводитись помилки в випадках неправильного вводу виразу:
9+3-4+-6 Error in expression (not right symbol)! - виводиться помилка про зайвий символ (рис.4)
Рис.4 Помилка про зайвий символ
((6+4-5)*7 Error in brackets! - виводиться помилка неправильного збалансування дужок (рис.5).
Рис.5 Помилка неправильного збалансування дужок
2+R-4*6 There is illegal symbol in expression! - виводиться помилка про неправильно введений операнд (рис.6 ).
Рис.6 Помилка про неправильно введений операнд
ВИСНОВКИ
В даній курсовій роботі я написав програму розбору та обчислення простих математичних виразів. Проаналізувавши її роботу, вона працює правильно. Тобто виконує чотири простих арифметичних дії, а саме: множення, ділення, додавання і віднімання, а також обчислює вирази з дужками. Якщо вираз записано не паравильно, програма виводить помилку.
В програмі я використав багато процедур і макросів, які описані в курсовій роботі. Програма получилась досить велика, але в кінці програми є невеличка, але основна частина, в якій закладений основний алгоритм. І саме ця основна частинка викликає всі процедури.
Моя програма може мати дуже велике практичне застосування. Тому що зараз в дуже багатьох сферах використовуються розрахунки чисел. Звісно на сьогодніший день є дуже багато мініатюрних пристроїв, які заміняють цю програму, тобто пристроїв для розрахунку. Сучасні пристрої можуть обчислювати надзвичайно складні операції, можуть розраховувати не лише прості арифметичні операції, але й складні вирази, обчислювати тригонометричні функції. Мою програму також можна удосконалити так, щоб вона обчислювала не лише прості арифметичні дії, але й дещо складніше, наприклад обчислення косинусів та синусів, знаходження інтегралів, розвязання логарифмів, але й звісно що й текст програми був би надзвичайно великий.
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ
1. Александр Крупнік «Ассемблер. Самоучитель»
2. Том Сван «Изучение языка ассемблера»
3. Зубков Сергей Владимирович «Assembler для Dos, Windows и Unix»
4. Абель П. «Язык Ассемблера для IBM PC и программирования»
5. Юров В., Хорошенко С. «Assembler: учебный курс»
6. Финогенов К.Г. «Самоучитель по системным функциям MS–DOS»
7. Том Сван «Освоение Turbo Assembler»
8. Пильщиков « Программирования на языке ассемблера IBM PC»
Додаток А
Текст програми
data segment
buffer db 512 dup(?)
Msg db 'wwedu wuraz i natusnu enter ',13,10,'$'
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
Errordujku db "Error in brackets!",13,10,'$'
Errorsumvol db "There is illegal symbol in expression!",13,10,'$'
Errordii db "Error in expression (not right symbol)!",13,10,'$'
minus db 0
a db "0000000000"
b db "0000000000"
data ends
code segment
assume cs:code,ds:data,es:data
Testsumvol macro str,len
lea si,string
mov cx,len
call Testsumvolr
endm
Testdujku macro string,len
mov cx,len
mov si,offset string
call TestdujkuT
endm
Testdii macro string,len
lea si,string
mov cx,len
call Testdiii
endm
SymIn macro string,symbol,len
push ax
push cx
push di
cld
mov cx,len
lea di,string
mov al,symbol
rep stos string
pop di
pop cx
pop ax
endm
dovjuna macro string,len,lenstring
mov cx,len
lea si,string
call lengstr
mov lenstring,bx
endm
InTmpExpr macro StringS,StringD,len,Open,Close
lea si,StringS
lea di,StringD
mov cx,len
call InTmpExpression
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
Init macro mem1,mem2,len
mov di,len-1+offset mem1
mov si,len-1+offset mem2
mov cx,len
endm
AddBCD macro mem1,mem2,len
Init mem1,mem2,len
call AddBCDp
endm
SubBCD MACRO mem1,mem2,len
Init mem1,mem2,len
call SubBCDp
endm
MulBCD macro mem1,mem2,len
Init mem1,mem2,len
call MulBCDp
endm
DivBCD macro mem1,mem2,len
mov di,offset mem1
mov si,offset mem2
mov cx,len
call DivBCDp
endm
OutBCD macro mem,len
mov si,offset mem
mov cx,len
call OutBCDp
endm
o4ustka macro
push ax
xor ah, ah
mov al, 2
int 10h
pop ax
endm
AddBCDp proc
push ax
push di
push si
push cx
std
clc
_add:
lodsb
adc al,[di]
aaa
stosb
loop _add
pop cx
pop si
pop di
pop ax
ret
endp
SubBCDp proc
push ax
push di
push si
push cx
std
clc
_sub:
lodsb
sbb [di],al
mov al,[di]
aas
stosb
loop _sub
pop cx
pop si
pop di
pop ax
ret
endp
MulBCDp proc
push ax
push bx
push di
push si
push cx
std
mov bx,offset buffer
mov dh,cl
push bx
shl cx,1
xor al,al
_0:
mov [bx],al
inc bx
loop _0
mov cl,dh
pop bx
_mul_o_:
xor dl,dl
push cx
push bx
push si
mov cl,dh
mul_i_:
lodsb
mul byte ptr [di]
aam
add al,dl
aaa
add al,[bx]
aaa
mov dl,ah
xor ah,ah
mov [bx],al
inc bx
loop mul_i_
mov [bx],dl
pop si
pop bx
inc bx
dec di
pop cx
loop _mul_o_
mov cl,dh
sub bx,cx
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
pop si
pop di
pop bx
pop ax
ret
endp
SubInvBCDp proc
push si
push di
add si,cx
dec si
add di,cx
dec di
call SubBCDp
pop di
pop si
ret
ENDP
CmpBCDp proc
push ax
push di
push si
push cx
cld
_cmp_:
lodsb
cmp al,[di]
jl _less_
jg _greater_
inc di
loop _cmp_
_less_:
stc
jc _cmp_q_
_greater_:
clc
_cmp_q_:
pop cx
pop si
pop di
pop ax
ret
endp
PrepForDiv proc
cld
push di
push si
push di
pop si
mov di,offset buffer
xor al,al
push cx
stosb
rep movsb
pop cx
stosb
pop si
push cx
_find_:
lodsb
dec cx
cmp al,0
je _find_
dec si
inc cx
mov dx,cx
rep movsb
pop cx
push cx
xor al,al
rep stosb
mov di,offset buffer
pop cx
mov si,di
inc cx
add si,cx
pop bx
ret
endp
DivBCDp proc
push ax
push bx
push di
push si
push cx
push di
call PrepForDiv
xor ax,ax
call CmpBCDp
jnc _next_1_
_div_:
call CmpBCDp
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
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
pop si
pop di
pop bx
pop ax
ret
endp
OutBCDp proc
mov ah,06h
cld
_out_:
lodsb
or al,30h
mov dl,al
int 21h
loop _out_
mov dl,0dh
int 21h
mov dl,0ah
int 21h
ret
endp
POV proc
mov ah,09h
mov dx,OFFSET Msg
int 21h
endp
Wwedennja proc
call EnterExpression
dovjuna string,200,len_str
Testsumvol string,len_str
cmp ax,0
jne ErrorEnd
Testdujku string,len_str
cmp ax,0
jne ErrorEnd
lea dx,expression
mov si,0
mov cx,len_str
inc cx
inc cx
mov bx,0
new:
mov di,0
ScanString:
mov al,string[si]
cmp al,39h
ja IsChar
cmp al,30h
jb IsChar
mov a[di],al
inc di
inc si
loop ScanString
jmp EndProc
IsChar:
mov bx,di
dec bx
call MoveInExpr
SymIn a,'0',10
SymIn b,'0',10
dec cx
inc si
cmp cx,0
jne new
EndProc:
mov ax,0
ErrorEnd:
ret
Wwedennja endp
EnterExpression proc
push ax
push bx
push cx
push si
mov si,0
mov cx,len_str
mov bx,cx
InString:
mov ah,01h
int 21h
cmp al,13
je EndInString
mov string[si],al
mov results[si],al
inc si
loop InString
EndInString:
mov al,'='
mov results[si],al
inc si
mov res_si,si
pop si
pop cx
pop bx
pop ax
ret
EnterExpression endp
Testsumvolr proc
push bx
push cx
push dx
push si
mov ax,0
mov dl,[si]
cmp dl,' '
je ErrorTest
inc cx
dec si
ScanExpr:
inc si
dec cx
mov dl,[si]
cmp dl,39h
ja chr
cmp dl,30h
jb chr
cmp cx,0
jae ScanExpr
mov ax,0
jmp EndTest
chr:
cmp dl,'+'
je ScanExpr
cmp dl,'-'
je ScanExpr
cmp dl,'*'
je ScanExpr
cmp dl,'/'
je ScanExpr
cmp dl,'('
je ScanExpr
cmp dl,')'
je ScanExpr
cmp dl,' '
je EndTest
ErrorTest:
mov ax,2
EndTest:
pop si
pop dx
pop cx
pop bx
ret
Testsumvolr endp
TestdujkuT proc
push bx
push di
push si
push cx
inc cx
mov di,sp
start2:
mov bl,[si]
cmp bl,' '
je endstart2
cmp bl,'('
je open
cmp bl,')'
je close
jne repeats
open:
push bx
jmp short repeats
close:
cmp sp,di
je repeats
pop bx
repeats:
inc si
loop start2
endstart2:
mov ax,sp
sub ax,di
cmp ax,0
je endtest1
EndErrorTest:
mov ax,1
endtest1:
mov sp,di
pop cx
pop si
pop di
pop bx
ret
endp
lengstr proc
push si
push dx
push cx
push ax
mov bx,cx
lengths:
mov dl,[si]
cmp dl,' '
je equel
inc si
loop lengths
equel:
mov ax,si
mov dl,[si]
sub bx,cx
dec bx
pop ax
pop cx
pop dx
pop si
ret
endp
MoveInExpr proc
push cx
push bx
push di
push si
cld
mov cx,10
mov al,'0'
lea di,a
repe scasb
cmp cx,0
je MoveChar
mov cx,10
cld
lea di,b
lea si,a
mov ax,9
sub ax,bx
add di,ax
mov cx,bx
inc cx
rep movsb
cld
lea si,b
mov di,dx
mov cx,10
rep movsb