Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
оотчет по курсовику.doc
Скачиваний:
2
Добавлен:
01.03.2025
Размер:
190.46 Кб
Скачать

Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования «Тольяттинский государственный университет» «ИНСТИТУТ ЭНЕРГЕТИКИ И ЭЛЕКТРОТЕХНИКИ» (институт, факультет) «Автоматизация технологических процессов и производств» (кафедра)

220400 «Управление в технических системах» (код и наименование направления подготовки, специальности)

Системы и средства автоматизации и управления (наименование профиля, специализации)

Курсовая работа

на тему Калькуляторы

Студент А.С.Миронов (И.О.Фамилия)

Руководитель О.Ю.Копша (И.О.Фамилия)

Тольятти 2013

Содержание.

Глава 1. Задание……………………………………………………….………3

Глава 2. Десятичный калькулятор

2.1 Текст программы с комментариями......................................................4-15

2.2 Пример исполнения.....................................................................................15

Глава 3. Двоичный калькулятор

3.1 Текст программы с комментариями.....................................................16-27

3.2 Пример исполнения.....................................................................................27

Задание.

Назначение и функции регистров. Помещение и обработка значений и математические действия над двумя трёхзначными числами. Осуществлять операции над ними: со знаком и без знака.

Написать программы, выполняющие действия математики над числами десятичной, двоичной и шестнадцатеричной систем счисления, вводя значения с клавиатуры.

Десятичный калькулятор.

name "calc2"

PUTC MACRO char

PUSH AX ;Данная команда помещает на вершину стека значение. Предыдущее значение, находящееся на вершине стека перемещается на один уровень вниз.

MOV AL, char ;поместить значение из памяти в регистр AL

MOV AH, 0Eh ;поместить значение из памяти в регистр AH

Int 10h ;Вызывание Dos

POP AX ;Перемещение всего содержимого стека на один уровень вверх. Предыдущее значение, находящееся на вершине стека утрачивается.

ENDM

org 100h

jmp start

; определяем переменные:

msg0 db "calculator.",0Dh,0Ah

db "use 2s numbers",0Dh,0Ah,'$'

msg1 db 0Dh,0Ah, 'enter first number: $'

msg2 db "enter the operator: + - * / : $"

msg3 db "enter second number: $"

msg4 db 0dh,0ah , 'the approximate result is : $'

msg5 db 0dh,0ah ,'press any key... ', 0Dh,0Ah, '$'

err1 db "wrong operator!", 0Dh,0Ah , '$'

smth db " and something.... $"

; оператор может быть: '+','-','*','/' или 'q' для выхода.

opr db '?'

; ввод первого и второго числа с клавиатуры:

num1 dw ?

num2 dw ?

start:

mov dx, offset msg0

mov ah, 9

int 21h

lea dx, msg1 ; получение эффективного адреса (смещения) источника.

mov ah, 09h ; вывод на экран сообщения 1 (Функция DOS)

int 21h

; получаем число введённое с клавиатуры

; результат в регистр cx:

call scan_num

; сохраняем первое число в сх:

mov num1, cx

; новая строка (функции DOS):

putc 0Dh

putc 0Ah

lea dx, msg2

mov ah, 09h ; вывод на экран сообщения 2

int 21h

; считываем оператор:

mov ah, 1 ; ввод с клавиатуры оператора.

int 21h

mov opr, al

; новая строка:

putc 0Dh

putc 0Ah

cmp opr, 'q' ; сравниваем с q, если да, то выход.

je exit

cmp opr, '*'

jb wrong_opr

cmp opr, '/'

ja wrong_opr

; вывод следущего сообщения

lea dx, msg3

mov ah, 09h

int 21h

; получаем число введённое с клавиатуры

; результат в регистр cx:

call scan_num

; сохраняем второе число в сх:

mov num2, cx

lea dx, msg4

mov ah, 09h ; вывод на экран сообщения

int 21h

; вычисляем:

cmp opr, '+' ;позволяет сравнить два числа, сохраняя результат своей работы во флагах.

je do_plus

cmp opr, '-'

je do_minus

cmp opr, '*'

je do_mult

cmp opr, '/'

je do_div

; в случае, если оператор не из перечисленных

wrong_opr:

lea dx, err1

mov ah, 09h ; вывод на экран сообщения об ошибке

int 21h

exit:

; вывод на экран сообщения о выходе

lea dx, msg5

mov ah, 09h

int 21h

; ждём нажатия клавишы...

mov ah, 0

int 16h

ret ; выход из процедуры.

do_plus:

mov ax, num1

add ax, num2

call print_num ; вызов процедуры печати значения.

jmp exit ;Эта команда выполняет безусловный переход.

do_minus:

mov ax, num1

sub ax, num2

call print_num ; вызов процедуры печати значения.

jmp exit

do_mult:

mov ax, num1

imul num2 ; (dx ax) = ax * num2.

call print_num ; вызов процедуры печати значения.

jmp exit

do_div:

mov dx, 0

mov ax, num1

idiv num2 ; ax = (dx ax) / num2.

cmp dx, 0

jnz approx

call print_num ; вызов процедуры печати значения.

jmp exit

approx:

call print_num ; вызов процедуры печати значения.

lea dx, smth

mov ah, 09h ; вывод на экран значения

int 21h

jmp exit

; получаем какое-то число (со знаком или без) с клавиатуры,

; и сохраняем в регистр СХ:

SCAN_NUM PROC NEAR

PUSH DX

PUSH AX

PUSH SI

MOV CX, 0

; сброс флага:

MOV CS:make_minus, 0

next_digit:

; получаем символ с клавиатуры

MOV AH, 00h

INT 16h

; печатаем его:

MOV AH, 0Eh

INT 10h

; проверка на минус:

CMP AL, '-' ;сравнение двух операндов.

JE set_minus ;условный переход = .

; проверка на нажатие клавиши <ENTER>:

CMP AL, 0Dh

JNE not_cr ;условный переход <>.

JMP stop_input

not_cr:

CMP AL, 8 ; <BACKSPACE> нажат?

JNE backspace_checked

MOV DX, 0 ; удалить последнюю цифру

MOV AX, CX ; путём деления:

DIV CS:ten ; AX = DX:AX / 10 (DX-rem).

MOV CX, AX

PUTC ' ' ; очистка последней позиции.

PUTC 8 ; пробел.

JMP next_digit

backspace_checked:

; учитывает только цифры:

CMP AL, '0'

JAE ok_AE_0

JMP remove_not_digit

ok_AE_0:

CMP AL, '9'

JBE ok_digit

remove_not_digit:

PUTC 8 ; пробел.

PUTC ' ' ; очистка последней позиции.

PUTC 8 ; пробел.

JMP next_digit ; ждём следущее "вложение".

ok_digit:

PUSH AX

MOV AX, CX

MUL CS:ten ; DX:AX = AX*10

MOV CX, AX

POP AX

; проверка числа. должно войти в 16бит

CMP DX, 0

JNE too_big

; преобразования из аскии кода:

SUB AL, 30h

; добавить AL в CX:

MOV AH, 0

MOV DX, CX ; резервное копирование, в случае если результат будет большим.

ADD CX, AX

JC too_big2 ; прыгаем дальше, если число слишком большое.

JMP next_digit

set_minus:

MOV CS:make_minus, 1

JMP next_digit

too_big2:

MOV CX, DX ; восстановить резервные значения перед сложением

MOV DX, 0 ; в DX ноль перед копированием

too_big:

MOV AX, CX

DIV CS:ten ; из DX:AX = AX*10, делаем AX = DX:AX / 10

MOV CX, AX

PUTC 8 ; пробел.

PUTC ' ' ; очистка послденей позиции.

PUTC 8 ; пробел.

JMP next_digit ; ждём нажатия клавишы.

stop_input:

; проверка флага:

CMP CS:make_minus, 0

JE not_minus

NEG CX

not_minus:

POP SI

POP AX

POP DX

RET

make_minus DB ? ; используем как флаг.

SCAN_NUM ENDP

; печатаем число в AX,

; используется с PRINT_NUM_UNS для печати чисел со знаком:

PRINT_NUM PROC NEAR

PUSH DX

PUSH AX

CMP AX, 0

JNZ not_zero

PUTC '0'

JMP printed

not_zero:

; проверка знака у AX,

; если отрецательный сделать абсолютным:

CMP AX, 0

JNS positive

NEG AX

PUTC '-'

positive:

CALL PRINT_NUM_UNS

printed:

POP AX

POP DX

RET

PRINT_NUM ENDP

; печать без знака

; число в АХ

; допускается значение от 0 до 65535 (FFFF)

PRINT_NUM_UNS PROC NEAR

PUSH AX

PUSH BX

PUSH CX

PUSH DX

; флаг для претвращения печати нуля перед числом

MOV CX, 1

MOV BX, 1000

; AX равен нулю?

CMP AX, 0

JZ print_zero

begin_print:

; проверка делителя (если нуль то переходим к end_print):

CMP BX,0

JZ end_print

; избегаем печать нуля перед числом:

CMP CX, 0

JE calc

; если AX<BX результат деления будет равен нулю:

CMP AX, BX

JB skip

calc:

MOV CX, 0 ; установка флага.

MOV DX, 0

DIV BX ; AX = DX:AX / BX (DX=остаток).

; печать последней цифры

; AH всегда нуль поэтому игнорируется

ADD AL, 30h ; преобразуем в аскии код.

PUTC AL

MOV AX, DX ; получаем остаток от последних делений.

skip:

; считаем BX=BX/2

PUSH AX

MOV DX, 0

MOV AX, BX

DIV CS:ten ; AX = DX:AX / 2 (DX=отстаток).

MOV BX, AX

POP AX

JMP begin_print

print_zero:

PUTC '0'

end_print:

POP DX

POP CX

POP BX

POP AX

RET

PRINT_NUM_UNS ENDP

ten DW 10 ; используем как число для двух выше описаных процедур

GET_STRING PROC NEAR

PUSH AX

PUSH CX

PUSH DI

PUSH DX

MOV CX, 0 ; счётчик символов.

CMP DX, 1 ; буффер слишком мал?

JBE empty_buffer ;

DEC DX ; резервируем место для последнего нуля.

; цикл для получения нажатой клавишы

wait_for_key:

MOV AH, 0 ; нажата клавиша.

INT 16h

CMP AL, 0Dh ; <RETURN> нажат?

JZ exit_GET_STRING

CMP AL, 8 ; <BACKSPACE> нажат?

JNE add_to_buffer

JCXZ wait_for_key ; ничего не нажато

DEC CX

DEC DI

PUTC 8 ; пробел.

PUTC ' ' ; чистим последнюю позицию .

PUTC 8 ; пробел.

JMP wait_for_key

add_to_buffer:

CMP CX, DX ; буффер переполнен?

JAE wait_for_key ; ждём нажатия <BACKSPACE> или <RETURN>...

MOV [DI], AL

INC DI

INC CX

; печатаем нажатие клавиши:

MOV AH, 0Eh

INT 10h

JMP wait_for_key

exit_GET_STRING:

; обнуляем:

MOV [DI], 0

empty_buffer:

POP DX

POP DI

POP CX

POP AX

RET

GET_STRING ENDP

Пример исполнения

Рис. 1 Скриншот работы десятичного калькулятора.

Двоичный калькулятор.

name "calc2"

PUTC MACRO char

PUSH AX ;Данная команда помещает на вершину стека значение. Предыдущее значение, находящееся на вершине стека перемещается на один уровень вниз.

MOV AL, char ;поместить значение из памяти в регистр AL

MOV AH, 0Eh ;поместить значение из памяти в регистр AH