Учебник по ассемблеру (ASM)
 

Ассемблер в примерах - Простейший калькулятор

Вопрос:
Помогите пожалуйста разработать простейший калькулятор, выполняющий сложение, умножение и вычитание целых чисел в диапазоне от 0 до 9.

Ответ:
.model tiny
.code
  JUMPS ; эта директива заставляет генерировать код, при котором можно писать условные 
        ; переходы на расстояние больше 128 байт (а тут такие есть)
org 100h
start:
   mov ax, 3
   int 10h
@@00:   
 lea  dx, msg_first
 CALL inputDEC
     mov a, al
 lea  dx, msg_second
 CALL inputDEC
     mov b, al
 lea dx, msg_op
 mov ah, 9
 int 21h
op01: 
 mov ah, 8
 int 21h     
  cmp al, '*'
  je  op_mul
  cmp al, '+'
  je  op_add
  cmp al, '-'
  je  op_sub
  cmp al, '/'
  je  op_div
    jmp op01 ; все остальные игнорируем
op_mul:
    mov  op, al
    mov  al, a
    mov  ah, b
    imul ah 
    mov  c, al
    jmp  show_result   
op_add:
    mov op, al
    mov al, a
    add al, b
    mov c, al
    jmp show_result
op_sub:
    mov op, al
    mov al, a
    sub al, b
    mov c, al
    jmp show_result
op_div:
    mov op, al
    mov bl, b
    or  bl, bl
    jz  op_no_div
       mov  al, a
       cbw        ; конвертировать байт в слово с сохранением знака
       idiv bl    ; знаковое деление
       mov  c, al
       jmp show_result
op_no_div:    
     lea dx, msg_no_div
     mov ah, 9
     int 21h
     jmp op_repeat 
show_result:
 lea dx, msg_res
 mov ah,9
 int 21h
 mov  al, a
 CALL writeDEC
 mov  al, op
 int 29h
 mov al, b
 CALL writeDEC
 mov al, '='
 int 29h
 mov al, c
 CALL writeDEC
 
op_repeat:
   lea dx, msg_repeat
   mov ah, 9
   int 21h

    mov ah, 8
    int 21h
    cmp al, 'y'
    je  @@00 
    cmp al, 'Y'
    je  @@00
    jmp @@_exit
  

  lea dx, PressKey
  mov ah,9
  int 21h

  xor ax, ax
  int 16h
@@_exit:
  int 20h
  
inputDEC proc
; возвратит число со знаком в AL
; при вводе в DX - адрес сообщения
push bx
  mov ah, 9
  int 21h
  xor bl, bl ; число 
  xor bh, bh ; флаг отрицательного будет
@@1_01:
    mov ah, 8
    int 21h
    cmp al, '-'
    jne @@1_digit
      inc bh
      int 29h ; покажем
      jmp @@1_01
@@1_digit:
     cmp  al, '0'
     jb   @@1_01 ; меньше нуля - игнорируем
     cmp  al, '9'
     ja   @@1_01
  ; значит цифра
        int 29h 
        sub al, '0' ; число и символ числа отличаются на код '0'
  or bh, bh ; проверим, установлен ли
  jz @@1_positive
     neg al
@@1_positive:   
pop  bx   
 ret
inputDEC endp  
  
writeDEC proc
; вывод числа в AL как десятичного со знаком
; -128 .. + 127
push ax
push bx
push cx
push dx
 or al, al
 jns @@positive ; если не установлен флаг знака 
 push ax
   mov ah, 2
   mov dl, '-'
   int 21h
 pop  ax  
   neg al 
 @@positive:
   xor cx, cx
   mov bl, 10
@@next_digit:
   xor  ah, ah
   div  bl
   push ax
   inc  cx
   or   al, al
   jnz @@next_digit
   
@@out_next_digit:
   pop  ax
   xchg ah, al   
   add  al, '0'    
   int  29h
   LOOP @@out_next_digit
 
pop  dx
pop  cx
pop  bx
pop  ax 
ret
writeDEC endp 

a   db ? ; первое число
b   db ? ; второе число
c   db ? ; результат
op  db ?

msg_first  db 13,10,'Введите первое число: $'
msg_second db 13,10,'Введите второе число: $'
msg_op     db 13,10,'Введите знак операции (+,-,*,/): $'
msg_res    db 13,10,'Результат: $'
msg_repeat db 13,10,'Повторить (Y/N)$'
msg_no_div db 13,10,'Деление невозможно$'
  
PressKey   db 13,10,'Press any key ...$'
end start

   Вперёд
   Содержание