Интересный калькулятор на 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

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

12   голосов , оценка 4.25 из 5
Похожие ответы