Интересный калькулятор на TASM - Assembler
Формулировка задачи:
Всем доброго времени суток. Такой вопрос: есть калькулятор, который выполняет 4 простейших арифметических операций с двумя числами. Задача заключается в том чтобы его немного модифицировать и упростить согласно тз: написать калькулятор, выполняющий над двумя знаковыми числами размером в слово следующие операции: нахождение максимального, минимального и среднего арифметического значений (все отдельно, можно через процедуры) ну и вывод их на экран соответственно.
Заранее спасибо!
Листинг программы
- .model tiny ;COM - файл
- .code
- .386 ;используем eax
- org 100h
- start:
- vvod1: ;выбор функции
- xor eax,eax ;обнуляем регистры
- xor edx,edx ;
- call clrscr
- mov ah,9 ;Вывод сторки мессаге1
- mov dx,offset message1 ;
- int 21h ;
- mov ah,08h ;считать символ с клавиатуры
- int 21h ;
- cmp al,'+' ;сравнение с '+'
- je cloj ;значит складываем
- cmp al,'-'
- je vich ;вычитание
- cmp al,'/'
- je dele ;деление
- cmp al,'*'
- je rr1 ;используем jmp т.к далеко
- jmp rr ;
- rr1: jmp umnoj ;Умножение
- rr: cmp al,'q' ;выход
- je quit
- cmp al,'Q'
- je quit
- jmp short vvod1 ;если не ввели то повторять ввод
- quit:
- ret ;Выход
- cloj: ;Сложение dx+ax->ax
- call clrscr ;стереть экран
- call aa1 ;ввод а
- push dx ;сохраняем dx в стеке
- call bb1 ;ввод b
- pop dx ;вытаскиваем dx из стека
- add ax,dx ;складываем ax и dx результат в eax
- call print
- call endstrd
- mov ah,9 ;Вывод сторки мессаге2
- mov dx,offset message2 ;
- int 21h
- mov ah,08h
- int 21h ;
- jmp vvod1
- vich: ;вычитание
- call clrscr ;стереть экран
- call aa1 ;ввод а
- push dx
- call bb1 ;ввод b
- pop dx
- sub dx,ax ;вычитаем из dx ax результат в edx
- mov ax,dx ;переносим его eax
- call print ;выводит eax в десятичной системе
- call endstrd
- mov ah,9 ;Вывод сторки мессаге2
- mov dx,offset message2 ;
- int 21h
- mov ah,08h
- int 21h ;
- jmp vvod1
- dele: ;деление (цело численное)
- call clrscr ;стереть экран
- call aa1 ;ввод а
- push dx
- call bb1 ;ввод b
- pop dx
- xchg dx,ax
- mov cx,dx ;сохраняем делитель в cx
- xor dx,dx ;обнуляем dx там будет остаток
- div cx ;делим результат в eax
- call print
- call endstrd
- mov ah,9 ;Вывод сторки мессаге2
- mov dx,offset message2 ;
- int 21h
- mov ah,08h
- int 21h ;
- jmp vvod1
- umnoj: ;умножение
- call clrscr ;стереть экран
- call aa1 ;ввод а
- push dx
- call bb1 ;ввод b
- pop dx
- mul edx ;умножаем результат в eax
- call print
- call endstrd
- mov ah,9 ;Вывод сторки мессаге2
- mov dx,offset message2 ;
- int 21h
- mov ah,08h
- int 21h ;
- jmp vvod1
- clrscr:
- xor dx,dx ;положение курсора dh-строка dl-столбец
- mov ah,02h ;установить в 0,0
- int 10h ;
- mov bl,0000111b ;атрибут символов белый на чёрном
- mov cx,25*80 ;количество символов
- mov ax,0920h ;вывод 25*80 пробелов
- int 10h ;
- ret
- endp
- aa1: ;ввод а
- mov dx,offset aaaa
- mov ah,9
- int 21h
- call mover
- mov dx,ax ;перенесём в dx
- ret
- endp
- bb1: ;ввод а
- mov dx,offset bbbb
- mov ah,9
- int 21h
- call mover
- ret
- endp
- mover:
- mov dx,offset bufer ;аресс буфера
- mov ah,0ah ;считать строку данных в буфер
- int 21h ;
- mov dx,offset endstr ;перенос курсора на строку ниже
- mov ah,9 ;
- int 21h ;
- ;перевод из строки в бинарное число
- xor di,di ;начало буферв
- xor ax,ax ;текущее значение ax
- mov cl,blength
- xor ch,ch
- xor bx,bx
- mov si,cx ;длинна буфера
- mov cl,10 ;множитель
- tohex:
- mov bl,byte ptr bconteg[di]
- sub bl,'0' ;цифра = код символа - код символа '0'
- jb tata ;если ко символа < чем код '0'
- cmp bl,9 ;или > чем '9'
- ja tata ;начать ввод занаво
- mul cx ;иначе умножить на 10
- add ax,bx ;добавить к ax новую цифру
- inc di ;увеличить адресс
- cmp di,si ;если он меньше чем кол. символов + 1
- jb tohex
- jmp tra
- tata: jmp vvod1 ;Нужно использовать дальний переход
- tra: ret
- endp
- print:
- mov ebx,0ah ;делитель
- xor cx,cx ;счётчик
- divloop:
- xor edx,edx ;обнуляем edx
- div ebx ;делим на 10
- add edx,'0' ;дописываем к остатку деления код нуля
- push edx ;сохраняем число в стеке
- inc cx ;увеличиваем счётчик на 1
- test eax,eax ;если есть что делить то
- jnz divloop ;продолжаем делить(если не ноль)
- restore:
- pop eax ;читаем записанные числа из стека
- mov edx,eax ;пишем их в eax
- mov ah,2 ;функция вывода символа по коду код в al
- int 21h ;
- dec cx ;уменьшаем счетчик
- cmp cx,0 ;если он не = нолю
- jne restore ;то проолжаем вывод
- ret
- endp
- endstrd:
- mov dx,offset endstr ;перенос курсора на строку ниже
- mov ah,9 ;
- int 21h ;
- ret
- endp
- ret
- message1 db "PRESS",0dh,0ah
- db "+ for add. a+b.",0dh,0ah
- db "- for sub. a-b",0dh,0ah
- db "/ for div. a/b",0dh,0ah
- db "* for mul. a*b",0dh,0ah
- db "q for quit",0dh,0ah,'$'
- message2 db "Press any key",0dh,0ah,'$'
- aaaa db "a=",'$'
- bbbb db "b=",'$'
- endstr db 0dh,0ah,'$'
- enderes db ' ',0dh,0ah,'$'
- bufer db 5 ;max размер ввода чисел
- blength db ? ;размер буфера после считывания
- bconteg: ;содержимое буфера будет за концом файла
- hexstring equ bconteg
- end start
Решение задачи: «Интересный калькулятор на TASM»
textual
Листинг программы
- LOCALS ;разрешение одинаковых локальных меток (начинающихся с @@)
- .model tiny ;COM - файл
- .code
- .386 ;используем eax
- org 100h
- start:
- vvod1: ;выбор функции
- call clrscr
- mov ah,9 ;Вывод сторки мессаге1
- mov dx,offset message1 ;
- int 21h ;
- mov ah,08h ;считать символ с клавиатуры
- int 21h ;
- Case1:
- cmp al,'m' ;сравнение с '+'
- jne Case2
- call EnterAB
- call Min ;значит возвращаем минимум
- call ShowResult
- jmp vvod1
- Case2:
- cmp al,'M'
- jne Case3
- call EnterAB
- call Max ;значит возвращаем максимум
- call ShowResult
- jmp vvod1
- Case3:
- cmp al,'a'
- jne Case4
- call EnterAB
- call Average ;значит возвращаем среднее арифметическое
- call ShowResult
- jmp vvod1
- Case4:
- cmp al,'q' ;выход
- je quit
- cmp al,'Q'
- je quit
- jmp short vvod1 ;если не ввели то повторять ввод
- quit:
- int 20h ;Выход
- ;Минимальное число
- ;на входе:
- ; ax - первое число
- ; bx - второе число
- ;на выходе:
- ; ax - минимальное из двух чисел
- Min proc
- cmp ax,bx
- jle @@Skip
- mov ax,bx
- @@Skip:
- ret
- Min endp
- ;Максимальное число
- ;на входе:
- ; ax - первое число
- ; bx - второе число
- ;на выходе:
- ; ax - максимальное из двух чисел
- Max proc
- cmp ax,bx
- jge @@Skip
- mov ax,bx
- @@Skip:
- ret
- Max endp
- ;Максимальное число
- ;на входе:
- ; ax - первое число
- ; bx - второе число
- ;на выходе:
- ; ax - максимальное из двух чисел
- Average proc
- add ax,bx ;складываем ax и bx результат в ax
- sar ax,1 ;делим на 2 при помощи арифметического сдвига
- ret
- Average endp
- ;ввод двух чисел для дальнейших вычислений
- ;на входе:
- ; -
- ;на выходе:
- ;ax - число A
- ;bx - число B
- EnterAB proc
- call clrscr
- @@ReadA:
- mov dx,offset aaaa
- mov ah,9
- int 21h
- mov ah, 0Ah
- lea dx, bufer
- int 21h
- lea si, bufer+1
- call Str2Num
- jc @@ReadA
- push ax
- call newstr
- @@ReadB:
- mov dx,offset bbbb
- mov ah,9
- int 21h
- mov ah, 0Ah
- lea dx, bufer
- int 21h
- lea si, bufer+1
- call Str2Num
- jc @@ReadB
- push ax
- call newstr
- pop bx
- pop ax
- ret
- EnterAB endp
- ;вывод строки результата и ожидание нажатия клавиши
- ;на входе
- ;ax - знаковое число для вывода в качестве результата
- ShowResult proc
- call Show_AX
- call NewStr
- mov ah,9
- mov dx,offset message2 ;
- int 21h
- mov ah,08h
- int 21h
- mov ah, 06h ;считываем второй символ при нажатии функциональной клавиши
- mov dl, 0FFh
- int 21h
- ret
- ShowResult endp
- ; преобразования строки в число
- ; на входе:
- ; ds:[si] - строка с числом
- ; на выходе
- ; ax - число
- ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен)
- Str2Num PROC
- LOCAL R: word
- pusha
- push ds
- push es
- push ds
- pop es
- mov cl, ds:[si]
- xor ch, ch
- jcxz @@Error
- push si ;для дальнейшей проверки знака
- inc si
- mov bx, 10
- xor ax, ax
- ;если в строке первый символ '-'
- ; - перейти к следующему
- ; - уменьшить количество рассматриваемых символов
- cmp byte ptr [si], '-'
- jne @@Loop
- inc si
- dec cx
- @@Loop:
- mul bx ; умножаем ax на 10 ( dx:ax=ax*bx )
- mov [di], ax ; игнорируем старшее слово
- cmp dx, 0 ; проверяем, результат на переполнение
- jnz @@ErrorWithPopSI
- mov al, [si] ; Преобразуем следующий символ в число
- cmp al, '0'
- jb @@ErrorWithPopSI
- cmp al, '9'
- ja @@ErrorWithPopSI
- sub al, '0'
- xor ah, ah
- add ax, [di]
- jc @@ErrorWithPopSI ; Если сумма больше 65535
- cmp ax, 8000h
- ja @@ErrorWithPopSI
- inc si
- loop @@Loop
- pop si ;проверка на знак
- inc si
- cmp byte ptr [si], '-'
- jne @@Check ;если должно быть положительным
- neg ax ;если должно быть отрицательным
- jmp @@StoreRes
- @@Check: ;дополнительная проверка, когда при вводе положительного числа получили отрицательное
- or ax, ax ;
- js @@Error
- @@StoreRes: ;сохранить результат
- mov R, ax
- clc
- pop es
- pop ds
- popa
- mov ax, R
- ret
- @@ErrorWithPopSI:
- pop si
- @@Error:
- xor ax, ax
- mov R, ax
- stc
- pop es
- pop ds
- popa
- mov ax, R
- ret
- Str2Num ENDP
- ; выводит число из регистра AX на экран
- ; входные данные:
- ; ax - число для отображения
- Show_AX proc
- push ax
- push bx
- push cx
- push dx
- push di
- mov cx, 10 ; cx - основание системы счисления
- xor di, di ; di - кол. цифр в числе
- ; если число в ax отрицательное, то
- ;1) напечатать '-'
- ;2) сделать ax положительным
- or ax, ax
- jns @@Conv
- push ax
- mov dx, '-'
- mov ah, 2 ; ah - функция вывода символа на экран
- int 21h
- pop ax
- neg ax
- @@Conv:
- xor dx, dx
- div cx ; dl = num mod 10
- add dl, '0' ; перевод в символьный формат
- inc di
- push dx ; складываем в стэк
- or ax, ax
- jnz @@Conv
- ; выводим из стека на экран
- @@Show:
- pop dx ; dl = очередной символ
- mov ah, 2 ; ah - функция вывода символа на экран
- int 21h
- dec di ; повторяем пока di<>0
- jnz @@Show
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- Show_AX endp
- clrscr proc
- pusha
- mov ax, 0700h ;функция SCROLL DOWN
- ;mov al, 10 ;число пустых строк, вдвигаемых сверху (0=очистить все окно)
- mov bh, 07h ;атрибут для заполнения
- mov cx, 0000h ;верхний левый угол окна (считая от 0)
- mov dx, 24*256+79 ;нижний правый угол окна (считая от 0)
- int 10h
- mov ah, 0Fh ;читать текущий видеорежим
- int 10h
- mov ah, 02h ;установить курсор в левый верхний угол
- mov dx, 0000h ;левый верхний угол
- int 10h
- popa
- ret
- clrscr endp
- newstr proc
- pusha
- mov ah, 09h
- lea dx, endstr
- int 21h
- popa
- ret
- newstr endp
- ;------------------------------------------------------------
- message1 db "PRESS",0dh,0ah
- db "m for min(a,b).",0dh,0ah
- db "M for max(a,b)",0dh,0ah
- db "a for (a+b)/2",0dh,0ah
- db "q for quit",0dh,0ah,'$'
- message2 db "Press any key",0dh,0ah,'$'
- aaaa db "a=",'$'
- bbbb db "b=",'$'
- endstr db 0dh,0ah,'$'
- enderes db ' ',0dh,0ah,'$'
- bufer db 5 ;max размер ввода чисел
- blength db ? ;размер буфера после считывания
- bconteg: ;содержимое буфера будет за концом файла
- end start
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д