Editor de texto em Assembly 3

 Editor de texto em Assembly que tem as funções de:
  • Escrever
  • Dar enter
  • Backspace
  • Justificar
  • Salvar arquivo de texto
  • Carregar aquivo ja salvo
 Créditos para Igor Leonardo, aluno de computação da UFMA.

%OUT--------------------------------------------------------------------------
%OUT Editor de texto - Justifica o texto, busca uma string  e salva em arquivo
%OUT Autor: Igor Leonardo Magalhães Ripardo                                  -
%OUT--------------------------------------------------------------------------
;Para compilar:                                                              -
;tasm igpad                                                                  -
;tlink igpad                                                                 -
;-----------------------------------------------------------------------------
.model small ;tamanho do segmento de dados
.stack 100h ;tamanho da pilha
.data ;segmento de dados, com definições de variáveis
;
TEXTO db 1600 dup('$') ;vetor de nome TEXTO com tamanho 1600 bytes
;-------------------------------------------------
;Strings Utilizadas na composição do Menu
;-------------------------------------------------
MENU1 db "<Escrever> Buscar Salvar Carregar Sair$"
MENU2 db "Escrever <Buscar> Salvar Carregar Sair$"
MENU3 db "Escrever Buscar <Salvar> Carregar Sair$"
MENU4 db "Escrever Buscar Salvar <Carregar> Sair$"
MENU5 db "Escrever Buscar Salvar Carregar <Sair>$"
MENSAGEM db " -    Utilize as setas do teclado para navegar no menu$"
MENSAGEM2 db " -    Crie um arquivo.txt no diretorio do programa para salvar o arquivo$"
;-------------------------------------------------
PALAVRA db 30 dup('$') ;vetor utilizado para armazenar umas string a ser busacada no documento de texto
MENSAGEM_BUSCA db "Digite uma palavra para buscar: $"
;Definições de variáveis para salvar em arquivo
NOME        DB    'arquivo.txt', 0
PONT_ARQ        DW    ?
BUFFER        DB    ?
SALVOU        DB    'O arquivo: arquivo.txt foi salvo no diretório padrão$'

.code
MAIN PROC                ;Inicia segmento de dados apontando para o início da área de dados
                        mov ax,@data
                        mov ds,ax

COMMENT *---------------------------------------------------------------------
Menu com as opções do usuário
------------------------------------------------------------------------------*
MENU:                    call LIMPA
                        lea dx,MENU1 ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM2 ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        mov ah,1h
                        int 21h
                        cmp al,4dh
                        je MUDA_MENU2
                        cmp al,0dh
                        je IR_ESCREVE_TEXTO
                        jmp MENU

IR_ESCREVE_TEXTO:         jmp ESCREVE_TEXTO
                   
MUDA_MENU2:                call LIMPA
                        lea dx,MENU2
                        mov ah,09h
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM2 ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        mov ah,1h
                        int 21h
                        cmp al,4bh
                        je MENU
                        cmp al,4dh
                        je MUDA_MENU3
                        cmp al,0dh
                        je IR_PROCURA
                        jmp MUDA_MENU2


IR_PROCURA:                jmp BUSCA
   
MUDA_MENU3:                call LIMPA
                        lea dx,MENU3
                        mov ah,09h
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM2 ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        mov ah,1h
                        int 21h
                        cmp al,4bh
                        je MUDA_MENU2
                        cmp al,4dh
                        je MUDA_MENU4
                        cmp al,0dh
                        je IR_CRIA_ARQUIVO
                        jmp MUDA_MENU3

IR_CRIA_ARQUIVO:        jmp CRIA_ARQUIVO                       

MUDA_MENU4:                call LIMPA
                        lea dx,MENU4
                        mov ah,09h
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM2 ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        mov ah,1h
                        int 21h
                        cmp al,4bh
                        je MUDA_MENU3
                        cmp al,4dh
                        je MUDA_MENU5
                        cmp al,0dh
                        je IR_CARREGA
                        jmp MUDA_MENU4

MUDA_MENU5:                call LIMPA
                        lea dx,MENU5
                        mov ah,09h
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        lea dx,MENSAGEM2 ;string a ser exibida
                        mov ah,09h ;função para exibir string
                        int 21h
                        call MUDA_LINHA
                        call MUDA_LINHA
                        mov ah,1h
                        int 21h
                        cmp al,4bh
                        je MUDA_MENU4
                        cmp al,0dh
                        je IR_SAIR
                        jmp MUDA_MENU5
                       
IR_SAIR:                jmp SAIR

COMMENT*----------------------------------------------------------------------------
- Recebe os caracteres digitados e armazena no vetor TEXTO
-----------------------------------------------------------------------------------*
   
ESCREVE_POP:            pop si
                        jmp LP_ESCREVE

ESCREVE_TEXTO:            call LIMPA
                        call IMPRIME

LP_ESCREVE:                mov ah,01h ;Função DOS para ler um caractere e escrever na tela
                        int 21h
                        cmp al,0dh ;verifica se enter foi digitado
                        jne NAO_MUDA_LINHA ;se for, aciona a rotina MUDA_LINHA
                        call MUDA_LINHA
NAO_MUDA_LINHA:
                        cmp al,08h
                        je IR_APAGA_LINHA
                        cmp al,1Bh ;1B = ESC
                        je IR_MENU
                        mov TEXTO[si],al ;guarda no vetor
                        inc si ;incrementa si para guardar próximo caractere na próxima posição do vetor
                        push si
                        mov ah,3h  ;esta função retorna em dl a coluna
                        int 10h
                        cmp dl,79    ;80 é a ultima coluna
                        je JUSTIFICAR ;MOV TEXTO[SI],AL
                        jmp ESCREVE_POP

IR_MENU:                jmp MENU           

IR_CARREGA:             jmp CARREGA

IR_APAGA_LINHA:         jmp APAGA_LINHA

comment*------------------------------------------------------------------------------
- Justifica o texto equilibtando espaços entre as palavras
- Desce a última palavra de uma linha se ela for maior que o espaço restante da linha
-------------------------------------------------------------------------------------*

JUSTIFICAR:                mov ah,1h ;Esse trecho verifica o caractere da última coluna digitado e decide o que fazer a depender do que o usuário digitou  
                        int 21h
                        cmp al,08h
                        je IR_APAGA_LINHA
                        cmp al,0dh
                        je ESCREVE_TEXTO
                        cmp al,' '
                        je ESCREVE_TEXTO
                        mov TEXTO[si],al
                        xor bl,bl ;zera BL para utilizá-lo como contador

LP_JUSTIFICAR:            dec si
                        inc bl
                        cmp TEXTO[si],' '
                        je VOLTA_TEXTO
                        jmp LP_JUSTIFICAR

VOLTA_TEXTO:            cmp TEXTO[si],'$'
                        je FIM_VOLTA_TEXTO
                        mov al,TEXTO[si+1]
                        mov TEXTO[si],al
                        inc si
                        jmp VOLTA_TEXTO

FIM_VOLTA_TEXTO:        dec si
                        push si

ADD_ESPACOS:            pop si
                        push si
                        mov cx,80

LP_ESPACOS:                dec si
                        cmp TEXTO[SI],' '
                        jne NAO_AFASTA_TEXTO
                        call SEPARA_TEXTO

NAO_AFASTA_TEXTO:        cmp bl,0
                        je FIM_ADD_ESPACOS
                        loop LP_ESPACOS
                        jmp ADD_ESPACOS

FIM_ADD_ESPACOS:        jmp ESCREVE_TEXTO

SEPARA_TEXTO:            push si ;guarda SI, posição atual do espaço
                        push ax ;guarda AX na pilha
                        push dx ;guarda DX na pilha
                        mov ax,si ;a posição do espaço fica em ax

VAI_PRO_FIM:            inc si ;incrementa SI, não usa POP pois não é necessário modificar o valor de SI
                        cmp TEXTO[si],'$'
                        je FIM_VAI_PRO_FIM
                        jmp VAI_PRO_FIM

FIM_VAI_PRO_FIM:        dec si

SEPARA:                    cmp ax,si ;quando AX for igual a SI termina o laço
                        je FIM_SEPARA
                        mov dl,TEXTO[si] ;coloca SI em dl para fazer a tribuição
                        mov TEXTO[si+1],dl ;coloca a posição anterior de SI na posição seguinte
                        dec si
                        jmp SEPARA ;esse trecho faz com que o texto se afaste uma posição desde o espaço, permitindo inserir outro espaço na palavra

FIM_SEPARA:                mov TEXTO[si+1],' '
                        dec bl
                        pop dx ;recupera os valores da pilha para utilizar índices  e contadores da posição guardada
                        pop ax ;recupera os valores da pilha para utilizar índices  e contadores da posição guardada
                        pop si ;recupera os valores da pilha para utilizar índices  e contadores da posição guardada

DECREMENTA:                dec si
                        dec cx
                        cmp si,0
                        je FIM_DECREMENTA
                        cmp TEXTO[si],' '
                        jne FIM_DECREMENTA
                        jmp DECREMENTA

FIM_DECREMENTA:            inc si
                        retn

COMMENT*-------------------------------------------------------------------------------
- Equivalente a função da tecla enter em editores de texto
--------------------------------------------------------------------------------------*
MUDA_LINHA:                push ax
                        mov ah,02h ;função DOS para imprimir caractere
                        mov dl,0dh ;caractere a ser impresso
                        int 21h
                        mov dl,0ah ; muda de linha
                        int 21h
                        pop ax
                        ret

COMMENT*-------------------------------------------------------------------------------
Equivalente a função da tecla backspace em editores de texto
--------------------------------------------------------------------------------------*
APAGA_LINHA:            ;esta rotina apaga o caractere anterior e torna para rotina que escreve no vetor TEXTO
                        cmp si,0
                        je FIM_APAGA
                        dec si ;coloca si referenciando o último caractere digitado para atribuir-lhe um símbolo
                        mov TEXTO[si],'$' ;atribui o símbolo $

FIM_APAGA:                jmp ESCREVE_TEXTO

APAGA_PALAVRA:             ;esta rotina apaga o caractere anterior e torna para rotina que escreve no vetor PALAVRA
                        dec si ;coloca si referenciando o último caractere digitado para atribuir-lhe um símbolo
                        mov PALAVRA[si],'$' ;atribui o símbolo $
                        call LIMPA ;junto com a rotina IMPRIME simula o efeito de apagar
                        call IMPRIME_PALAVRA ;junto com a rotina LIMPA simula o efeito de apagar
                        jmp LP_ESCREVE_PALAVRA   

COMMENT*--------------------------------------------------------------------------------
Esta sub-rotina serve pra compor a rotina APAGA_LINHA, ela imprime todo o vetor TEXTO
---------------------------------------------------------------------------------------*

IMPRIME:                push ax
                        xor si,si ;zera o vetor si a fim de acionar a posição inicial do vetor TEXTO
LOOP_IMPRIME:
                        mov al,TEXTO[si] ;é necessário colocar em al para comparar seu conteúdo
                        cmp al,'$' ;compara determinado elemento do vetor TEXTO com o caractere $
                        je FIM_LOOP
                        mov ah,02h ;função DOS para imprimir uma string
                        mov dl,TEXTO[si] ;string a ser impressa, deve ser colcada em dl
                        int 21h
                        inc si ;incrementa si para continuar o loop
                        jmp LOOP_IMPRIME

FIM_LOOP:                pop AX
                        ret

COMMENT*-------------------------------------------------------------------------------
- Esta rotina serve pra compor a rotina APAGA_PALAVRA, ela imprime todo o vetor PALAVRA
---------------------------------------------------------------------------------------*

IMPRIME_PALAVRA:        push ax
                        xor si,si ;zera o vetor si a fim de acionar a posição inicial do vetor TEXTO

LOOP_IMPRIME_P:            mov al,PALAVRA[si] ;é necessário colocar em al para comparar seu conteúdo
                        cmp al,'$' ;compara determinado elemento do vetor TEXTO com o caractere $
                        je FIM_LOOP_P
                        mov ah,02h ;função DOS para imprimir uma string
                        mov dl,PALAVRA[si] ;string a ser impressa, deve ser colcada em dl
                        int 21h
                        inc si ;incrementa si para continuar o loop
                        jmp LOOP_IMPRIME_P

FIM_LOOP_P:                pop AX
                        ret

COMMENT*--------------------------------------------------------------------
- Esta rotina limpa a tela do prompt, compõe várias rotinas do programa
---------------------------------------------------------------------------*

LIMPA:                     push ax
                        mov ah,0h         ; Ativa a IRQ 10 para a limpeza do vídeo
                        mov al,3h         ; define o modo de video
                        int 10h           ; Habilita a IRQ 10 (video)
                        pop ax
                        ret

COMMENT*--------------------------------------------------------------------
Rotina procura uma string no vetor TEXTO
---------------------------------------------------------------------------*
BUSCA:                    xor si,si ;zera o registrador si para reutilizá-lo como índice

PROCURA_STRING:            call LIMPA
                        lea dx,MENSAGEM_BUSCA ;string a ser exibida
                        mov ah,09h ;função para exibir string       
                        int 21h
                        call MUDA_LINHA

LP_ESCREVE_PALAVRA:        mov ah,01h ;função DOS para receber um caractere
                        int 21h
                        cmp al,0Dh ;compara com a tecla enter
                        je PERCORRE_VET ;se enter foi pressionada, a rotina de busca é iniciada
                        cmp al,08h ;compara com a tecla backspace
                        je APAGA_PALAVRA
                        mov PALAVRA[si],al ;se não, guarda o caractere digitado no vetor PALAVRA
                        inc si
                        jmp LP_ESCREVE_PALAVRA ;volta ao início da rotina até que enter seja pressionado

COMMENT*------------------------------------------------------------------------------
- Inicia as rotinas de busca:
    - Procura a primeira letra da palavra a ser buscada no vetor TEXTO
    - Se encontrar, compara cada caractere a partir dela nos vetores TEXTO e PALAVRA
    - Se a comparação for bem sucedida destaca as palavras encontradas
-------------------------------------------------------------------------------------*
PERCORRE_VET:            call LIMPA
                        xor si,si ;zera SI

LP_PERCORRE_VET:        cmp TEXTO[si],'$' ;compara a posição SI do vetor com o carctere SI
                        je RETORNA_MENU ;se for igual encerra a comparação
                        mov al,PALAVRA[0] ;coloca a primeira posição do vetor em AL
                        cmp si,0 ;esse teste verifica se ainda está na primeira iteração
                        je PULA_TESTE ;se estiver o teste adiante é desnecessário
                        cmp TEXTO[si-1],' ' ;se não estiver verifica se o caractere anterior é ' '(espaço)
                        jne REINICIA

PULA_TESTE:                cmp TEXTO[si],al ;verifica se a primeira letra do vetor guardada em AL é igual a algum elemento do vetor TEXTO
                        jne REINICIA ;se não forem iguais aciona uma rotina que reinicia a busca

TESTAR_IGUALDADE:        xor bx,bx
                        mov ah,2H         ;FUNÇÃO PRA IMPRIMIR
                        mov dl,TEXTO[si]    ;O QUE VAI SER IMPRESSO FICA EM DL
                        int 21H

LP_TESTE:                inc bx ;incrementa a cada iteração do LOOP
                        inc si ;incrementa a cada iteração do LOOP
                        cmp TEXTO[SI],' ' ;verifica se espaço foi encontrado, que indica o final de uma palavra no vetor texto
                        je FIM_LP_TESTE ;se encontrar um espaço encerra a iteração
                        cmp TEXTO[SI],'$' ;verifica se o caractere '$' foi encontrado, que indica o final do vetor texto
                        je FIM_LP_TESTE ;se encontrar o cactere descrito acima encerra a iteração
                        push si ;guarda SI na pilha, guarda si para "gravar" a posição atual da primeira letra
                        mov si,bx ;coloca BX em SI, BX faz a iteração do início do vetor a cada teste
                        cmp PALAVRA[si],'$' ;verifica se a palavra chegou ao fim
                        je POP_SI
                        pop si
                        mov al,TEXTO[si] ;coloca o caractere da posição SI em AL para efetuar uma comparação adiante
                        push si ;guarda o valor atual de SI
                        mov si,bx ;coloca BX em SI para continuar com a iteração no LOOP
                        cmp al,PALAVRA[si] ;compara o caractere do vetor TEXTO em AL com o caractere do vetor PALAVRA na posição SI
                        jne pop_si ;se forem diferentes encerra a iteração
                        pop si
                        mov ah,2h         ;função pra imprimir
                        mov dl,TEXTO[si]        ;o que vai ser impresso fica em dl
                        int 21h
                        jmp LP_TESTE

POP_SI:                    pop si ;tira si da pilha
                        jmp FIM_LP_TESTE ;

REINICIA:                mov ah,2h         ;função pra imprimir
                        mov dl,TEXTO[si]        ;o que vai ser impresso fica em dl
                        int 21h
                        inc si
                        jmp LP_PERCORRE_VET ;volta para procurar a primeira letra após a última encontrada

RETORNA_MENU:            mov ah,1h         ;função para ler
                        int 21h
                        jmp MAIN ;encerra a busca e retorna ao menu

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
JMP_PERCORRE_VET:        jmp LP_PERCORRE_VET
JMP_APAGA_LINHA:        jmp APAGA_LINHA
JMP_LP_ESCREVE:         jmp LP_ESCREVE
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

FIM_LP_TESTE:            push si ;guarda si para não perder o valor ao realizar a operação adiante
                        mov si,bx ;coloca BX em SI
                        cmp PALAVRA[si],'$' ;verifica se a palavra chegou ao fim
                        je VERIFICA_TEXTO
                        pop si ;recupera o valor de SI
                        jmp LP_PERCORRE_VET
   
VERIFICA_TEXTO:            pop si ;recupera o valor de si guardado na rotina FIM_LP_TESTE
                        cmp TEXTO[si],' ' ;compara a posição si do vetor TEXTO com ' '
                        je MARCAR
                        cmp TEXTO[si],'$'
                        je MARCAR
                        jmp JMP_PERCORRE_VET
   
MARCAR:                    cmp si,0 ;condição de parada
                        je LP_COLORIR ;se SI for zero então está no início da palavra
                        dec si ;decrementa SI até chegar na condição de parada
                        cmp TEXTO[si],' ' ;ao encontrar um espaço aciona a rotina que vai colorir a palavra encontrada
                        je COLORIR
                        mov ah,2h         ;função pra imprimir
                        mov dl,08h        ;o que vai ser impresso fica em dl
                        int 21h
                        jmp MARCAR

COLORIR:                inc si
                       

LP_COLORIR:                cmp TEXTO[si],' ' ;compara a posição SI do vetor TEXTO com ' ', essa a condição de parada do LOOP
                        je JMP_PERCORRE_VET
                        cmp TEXTO[si],'$' ;outra condição de parada do LOOP
                        je JMP_PERCORRE_VET
                        mov ah,09h      ; função obs: essa fução não movimenta o cursor, isso faz com que o vetor imprima colorido por cima do caractere
                        mov al,' '      ;carac a ser impresso
                        mov bh,0         ; página
                        mov bl,0fh       
                        mov cx,1h         ;quantas vezes o carac vai ser impresso
                        int 10h
                        mov ah,2h         ;função pra imprimir
                        mov dl,TEXTO[si]       ;o que vai ser impresso fica em dl
                        int 21h
                        inc si
                        jmp LP_COLORIR

COMMENT*------------------------------------------------------------------------------------
- Rotinas para salavar o vetor TEXTO em um arquivo com extensão txt
--------------------------------------------------------------------------------------------*                       

CRIA_ARQUIVO:            mov ah,3ch                ; cria o arquivo
                        mov cx,0                ; 0 = arquivo normal
                        mov dx,OFFSET NOME        ; nome e ext. do arquivo na string
                        int 21h
   
ABRE_ARQUIVO:            mov ah,3dh                ; função para abrir um arquivo
                        mov al,1h                ; arquivo para escrita
                        lea dx,NOME            ; abre o arquivo
                        int 21h
                        mov PONT_ARQ,ax        ; salva o handle
   
ESCREVE:                mov bx,PONT_ARQ        ; grava randle no bx
                        mov dx,OFFSET TEXTO        ; pega o texto
                        mov ah,40h                ; função para escrever a string no arquivo
                        mov cx,si                ; quantidade de bytes a gravar,
                        int 21h                    ; o tamanho do vetor é o tamanho de SI

TUDO_OK:                call MUDA_LINHA
                        lea dx,SALVOU    ; exibe a mensagem de arquivo salvo
                        mov ah,9
                        int 21h
                        call MUDA_LINHA
                        jmp FIM_SALVA

FIM_SALVA:                mov bx,PONT_ARQ    ; handle associado
                        mov ah,3eh        ; função que fecha um arquivo
                        int 21h
                        jmp SAIR        ; sai do programa
   
CARREGA:                call LIMPA
                        mov dx,offset NOME    ; offset do arquivo em 0d
                        mov al,2                ; leitura e escrita
                        mov ah,3dh                ; abre o arquivo
                        int 21h
                        mov PONT_ARQ,ax            ; guarda o handle

PRINT_FILE:                mov ah,3fh        ; le do arquivo
                        lea    dx,BUFFER    ; endereço do data buffer
                        mov cx,1        ; le 1 byte
                        mov bx,PONT_ARQ    ; pega o handle do arquivo
                        int 21h
                        cmp ax,cx    ; end of file?
                        jne FIM_ARQ
                        mov al,BUFFER    ; pega o caracter lido
                        call WRITE
                        jmp PRINT_FILE

WRITE:                    mov ah,2    ; prepara para exibir
                        mov dl,al
                        int 21h
                        ret

FIM_ARQ:                mov bx,PONT_ARQ
                        mov ah,3eh    ; fecha o arquivo
                        int 21h
                        jmp LP_ESCREVE

SAIR:                    mov ah,4ch    ;função para retorno ao dos
                        int 21h


MAIN   ENDP
   END   MAIN