Calculadora

Posted on March 6, 2010, 11:39 pm UTC by Iago Sousa (about 1 year ago)

Code (highlighted for ASM)

  1. [bits 16]    ; Vamos utilizar um assembly de 16 bits, para poder usar as interrupções.
  2. [org 0x100]  ; Para usar um 16 bits, temos que iniciar no endereço 0x100 da memória.
  3.  
  4. section .data ; Dados inicializados.
  5.         prompt dw "O que voce deseja?", 0x0A, 0x0D
  6.                    dw "1. Somar", 0x0A, 0x0D
  7.                    dw "2. Subtrair", 0x0A, 0x0D
  8.                    dw "3. Multiplicar", 0x0A, 0x0D
  9.                    dw "4. Dividir", 0x0A, 0x0D, 0x24
  10.         first  dw "Insira um numero, ele sera adicionado de 1: ", 0x24
  11.         secnd  dw "Voce inseriu: "
  12.         char   dq 0
  13.         err    dw "Nao utilize teclas virtuais como F1!", 0x24
  14.         err2   dw "Insira apenas numeros!", 0x24
  15. section .text ; Todo o código.
  16. global main   ; Dizemos que a main pode ser chamada por qualquer programa.
  17. main:         ; A "label" main, "label" significa rótulo.
  18.         call    cls           ; Chamamos a label cls, para limpar a tela.
  19.         mov     dx, prompt    ; Movemos o valor do endereço da variavel prompt para o registrador
  20.                               ; dx.
  21.         mov     ax, 0x0900
  22.         int     0x21
  23.         xor     ax, ax
  24.         int     0x16
  25.         sub     al, 0x30
  26.         test    al, al
  27.         jz              mm
  28.         cmp     al, 0x09
  29.         jg              mm
  30.         cmp     al, 0x01
  31.         je              sum
  32.         cmp     al, 0x02
  33.         je              sbt
  34.         cmp             al, 0x03
  35.         je              mll
  36.         cmp     al, 0x04
  37.         je              dvv
  38.         mov     dx, first     ; Movemos o valor do endereço da variável first para o registrador
  39.                               ; dx.
  40.         mov     ax, 0x0900    ; Movemos o valor 09 para o high level do registrador ax, o ah.
  41.         int     0x21          ; Interrupção 21 do processador. A int 21 é a int para funções do
  42.                               ; DOS.
  43.         xor     di, di        ; Zeramos o valor de di, isso é um truque, bastar analizar o que o
  44.                               ; XOR faz.
  45.         call    get           ; Chamamos a label get, para pegar todos os caracteres até que o
  46.                               ; 0x0d <enter> seja pressionado.
  47.         call    cls           ; Novamente chamamos a label cls para limpar a tela.
  48.         mov     dx, secnd     ; Movemos o valor do endereço da variável secnd para o registrador
  49.                               ; dx.
  50.         mov     ax, 0x0900    ; Movemons o valor 09 para o high level novamente!
  51.         int     0x21          ; A int 21 (não diga).
  52.         jmp             quit          ; Saltamos para o fim do script chamando a label quit para
  53.                               ; terminar o programa.
  54.        
  55. get:                      ; Label get, encarregada de pegar os caracteres pressionados pelo
  56.                           ; usuário até que o <enter> seja pressionado e assim liberando o
  57.                                                   ; "loop"
  58.         xor             ax, ax        ; Zerando o registrador ax
  59.         int     0x16          ; A int 16 do processador. A int 16 é encarregada do teclado.
  60.         test    al, al        ; TESTando o al, o "test" é igual o "and" só que não altera o
  61.                               ; valor do primeiro parâmetro (al)!
  62.         jz              zero          ; Se for zero vai pra label zero.
  63.         cmp     al, 0x0D      ; Compara o registrador al com o 0x0D (enter), para sair do "loop".
  64.         je              .finish       ; Se for <enter> pula para o sub-label finish.
  65.         sub     al, 0x30      ; Se não for, subtrai 30 do registrador al e o resultado vai para o
  66.                               ; registrador al!
  67.         test    al, al        ; Compara o registrador al com 1.
  68.         jz              mm            ; Se for menor (jump if less) então pula para a label mm.
  69.         cmp     al, 0x09      ; Compara o registrador al com 9.
  70.         jg              mm                        ; Se for maior (jump if greater) então pula para a label mm.
  71.         mov     [char+di], al ; Move o valor de al para o endereço "char+di", é adicionado de di
  72.                               ; para nunca sobreescrever o caractere anterior.
  73.         inc     di            ; Adiciona 1 ao registrador di.
  74.         jmp             get           ; Pula para o get, assim fazendo o "loop".
  75.         .finish:
  76.                 mov     al, 0x24  ; Move o valor 0x24 ($) para o registrador al, o "$" é usado para
  77.                                   ; Finalizar uma string.
  78.                 mov     [char+di], al ; O mesmo procedimento acima.
  79.                 ret               ; Retorna para depois de ser chamado.
  80.                
  81. mm:
  82.         mov     dx, err2
  83.         mov     ax, 0x0900
  84.         int     0x21
  85.         jmp     get
  86.                
  87. zero:                     ; Label zero
  88.         call    cls           ; Chama a label cls
  89.         mov     dx, err       ; Move o valor do endereço da variável err para o registrador dx
  90.         mov     ax, 0x0900    ; Movemons o valor 09 para o high level novamente!
  91.         int     0x21          ; A int 21...
  92.         jmp     main          ; Pulamos para o começo do código, a label main.
  93.                
  94. cls:                      ; Label cls
  95.         mov     ax, 0x0600    ; Movemons o valor 06 para o high level do registrador ax, o ah.
  96.         mov     bh, 0x07      ; Aqui é o atributo para cada byte da janela do prompt, o atributo
  97.                               ; 7 é a cor do texto, no caso de eu inserir A o texto irá ser verde
  98.         xor     cx, cx        ; Zerando o cx
  99.         mov     dx, 0x2479    ; Movemos o valor 2479h para o registrador dx, a janela padrão do
  100.                               ; prompt tem 80x25 de tamanho, que vai de 0x0 até 79x24, isso porque
  101.                                                   ; o zero não é ignorado, então o 2479 é o inverso de 79x24, foi
  102.                                                   ; usado para limpar toda a tela.
  103.         int     0x10          ; A int 10, responsável pelo vídeo.
  104.         mov     ax, 0x0200    ; ...
  105.         mov     bh, 0x00      ; ...
  106.         xor     dx, dx        ; ...
  107.         int     0x10          ; A int 10, responsável pelo vídeo.
  108.         ret                   ; Retorna para depois de ser chamado.
  109.        
  110. quit:                     ; Label quit
  111.         int     0x20          ; Int 20 é usada para sair do programa