Laboratório de Sistemas Processadores e Periféricos Sistema de Interrupções do 8086 Prática 11 Gustavo G. Parma Assunto: sistema de interrupcões do 8086. Interrupções do DOS Objetivos: Apresentação do sistema de interrupções do processador. Estudo das interrupções do DOS, principalmente a int21h. O aluno deverá ser capaz de entrar com um dado via teclado e apresentar um resultado na tela. 1 Introdução Teórica Para que não seja necessário que o processador fique monitorando sempre todos os periféricos conectados a ele (teclado, vídeo, interface serial, etc) cada interface possui seu próprio controlador e, quando necessário, esse controlador envia um sinal ao processador. O mecanismo de aviso é chamado de interrupção. Desta forma, o processador pode executar uma determinada tarefa e, quando ele receber um sinal de interrupção, pode ou não atende-la. O atendimento de uma interrupção, pelo processador, envolve em interromper o atual processamento e executar uma rotina que está associada ao sinal da interrupção. Para executar a rotina de interrupção, o processador tem que ser capaz de salvar todas as informações sobre o que ele estava fazendo para que seja possível, ao término da rotina de interrupção, voltar exatamente ao ponto anterior ao recebimento da interrupção. O atendimento ou não de um sinal de interrupção é controlado pelo flag IF. Se este flag for igual a zero, o processador irá ignorar os sinais de interrupção. Somente quando IF=1 o processador atenderá a solicitação de interrupção. Entretanto, existe um tipo de interrupção que não pode ser ignorada, ou mascarada, a chamada interrupção não mascarável (NMI). Esta interrupção ocorre sempre que existe um erro de paridade na memória. O atendimento a uma interrupção é tratada por uma sub-rotina associada ao número da interrupção. Quando o processador recebe um sinal de interrupção, os flags IF e TF são colocados em zero para evitar que uma outra interrupção seja recebida antes do atendimento da primeira. O valor dos flags, do registrador CS e logo após o IP são, então, colocados na pilha. Dessa forma, o processador sabe exatamente em que ponto do programa ele parou para atender a interrupção. Após salvar o conteúdo de CS e IP, o processador chama a rotina de interrupção, cujo endereço inicial do código vai estar alocado em um endereço específico da memória. Quando a rotina é completada, o processador retira da pilha o valor de CS e de IP, retornando ao ponto que ele estava antes do pedido de interrupção. A finalização de uma rotina de interrupção é caracterizada pela instrução IRET. O 8086 identifica a fonte de interrupção por um tipo, representado por um byte. Ou seja, existem 256 tipos diferentes de interrupção. Quando o processador detecta o pedido de interrupção, ele recebe um byte, indicando a origem e, portanto, sendo capaz de determinar a rotina de tratamento da interrupção. O primeiro 1K de memória, iniciando na posição 0000 : 0000 à posição 0000 : 03F F é reservado para guardar o endereço das rotinas de interrupção. Cada endereço é composto por 4 bytes, sendo as duas primeiras posições o offset e as duas seguintes o seguimento de memória no qual a rotina está alocada. Portanto, para identificar o endereço no qual estão alocadas as informações sobre uma rotina de interrupção, após receber o sinal de interrupção, o processador multiplica o byte recebido por quatro, localizando o endereço inicial no qual estará armazenado o IP da rotina. Por exemplo, se o processador receber um sinal de INT 12, ele multiplicará o número 12 por quatro, obtendo o endereço 0000 : 0030. O conteúdo deste endereço será colocado na parte baixa
de IP, o conteúdo de 0000 : 0031 será colocado na parte alta de IP, o conteúdo de 0000 : 0032 será colocado na parte baixa de CS e, finalmente, o conteúdo de 0000 : 0033 será colocado na parte alta de CS. Logo após o processador passará a executar o programa alocado no endereço dado por CS:IP. As posições de memória na qual estão alocados os endereços das rotinas de interrupção são chamadas de vetores de interrupção. A seqüência a seguir mostra os passos executados pelo processador para o atendimento a uma solicitação de interrupção. 1. Os flags são salvos na pilha; 2. O CS é salvo na pilha; 3. O IP é salvo na pilha; 4. 0 8086 determina o tipo (ou número) de interrupção; 5. A CPU determina o endereço da rotina que irá tratar essa interrupção; 6. Os dois primeiros bytes são colocados no IP; 7. Os dois seguintes são colocados no CS; 8. O processador passa a executar o programa alocado em CS:IP; 9. A rotina de interrupção é executada e finalizada pela instrução IRET; 10. O IP do ponto interrompido é retirado da pilha; 11. O CS do ponto interrompido é retirado da pilha; 12. Os flags são retirados da pilha; 13. O processador volta a executar o programa que estava rodando antes da interrupção. É importante ressaltar que os demais registradores não são automaticamente salvos. Isso implica em que, caso a rotina de interrupção altere algum registrador, é de responsabilidade do programador salvar o conteúdo dos registradores. Para isso pode-se utilizar as instrução PUSH e POP. A primeira coloca o conteúdo de um registrador ou memória, identificado pela fonte, na pilha (PUSH fonte) e a segunda retira uma palavra armazenada no topo da pilha colocando-a no registrador ou posição de memória identificado pelo destino (POP destino). Portanto, para cada instrução PUSH, ao final da rotina deve haver sempre uma instrução POP. O espaço de memória de 1K, reservado aos vetores de interrupção, é dividido em três partes, em função do tipo de interrupção. O endereço 0000 : 0000 à 0000 : 0013 é reservado para instruções geradas pelo próprio processador, chamados de vetores de interrupção dedicados (00:Erro de divisão, 01: Único passo, gerada se TF=1; 02:NMI - erro de paridade de memória; 03:breakpoint; 04: overflow). Um segundo grupo de vetores de interrupção, do endereço 0000 : 0014 à 0000 : 007F são vetores de interrupção reservados, incluíndo-se neste grupo as interrupções de hardware de IRQ0 à IRQ7. Os endereços 0000 : 0080 à 0000 : 03F F são disponíveis para que o programador armazene seus próprios vetores de interrupção. 2
1.1 Interrupções do DOS Ao se carregar o sistema operacional (SO) em um computador, este sistema aloca uma determinada quantidade de vetores de interrupção, utilizadas para gerenciar os dispositivos de entrada/saída (E/S) presentes. Desta forma, após a carga do SO, o computador estará pronto a executar outros programas e, assim que um dispositivo gerar um pedido de interrupção, a rotina de interrupção previamente alocada pelo SO será executada. Uma das interrupções mais utilizadas do DOS é a INT21h, que permite o acesso a um grande grupo de rotinas secundárias. A utilização da interrupção 21h do DOS permite o controle sobre vários dispositivos, sendo que a seleção da rotina secundária a ser utilizada é feita em função do conteúdo dos registradores, principalmente do registrador AX. Desta forma, são criadas várias funções, definidas em função de um valor de entrada presente no registrador AH. O valor de retorno da função é armazenado em AL. Algumas vezes, outro registrador pode ser necessário para a execução da função. A seguir serão mostradas, simplificadamente, algumas funções da INT21h. 1. Função 1 Aguarda a digitação de um caracter, armazenando o seu valor (em ASCII) em AL e ecoando-a na tela. Se o valor de AL for igual a zero, isso significa que uma tecla especial foi pressionada. e a função deve ser repetida imediatamente para que o valor da tecla seja armazenado em AL. Entrada: AH=1 Saída: AL= caracter digitado (em ASCII) 2. Função 2 Escreve um único caracter na tela, tratando o significado de caracteres de controle do código ASCII como o CR,LF e etc. Entrada: (a) AH=2 (b) DL:código do caracter a ser mostrado na tela. 3. Função 7 Semelhante à função 1, porém não existe o eco na tela e não pode ser interrompida pelo comando Control-Break ou Control-C (esse comando é interpretado como se apenas o caracter C tivesse sido pressionado). Entrada: AH=7 Saída: AL= caracter digitado (em ASCII) 4. Função 8 Semelhante à função 1, porém não existe o eco na tela e pode ser interrompida pelo comando Control-Break ou Control-C (esse comando é interpretado como se apenas o caracter C tivesse sido pressionado). Entrada: AH=8 Saída: AL= caracter digitado (em ASCII) 5. Função 9 Imprime na tela uma cadeia de caracteres. o caracter $ delimita o fim da cadeia. Entrada (a) AH=9 3
(b) DX=endereço inicial da string (DS deve apontar para o segmento onde a string esta armazenada) Saída: nenhuma 6. Função 0Ah Recebe uma string pelo teclado. Os registradores DS:DX apontam para a área na qual serão colocados os dados. O primeiro byte desta área deve conter o número de caracteres que serão recebidos. O DOS retorna, no segundo byte desta área, o número de caracteres efetivamente lidos. O caracter CR (Carriage Return - 0Dh) marca o fim da string lida e não é contabilizado pelo contador de caracteres devolvidos pelo DOS. Entrada: (a) AH=0Ah (b) DX=endereço inicial (DS deve apontar para o segmento onde esta a variavel que recebera os dados) DX =número de bytes a serem lidos Saída: DX+1 =total de caracteres efetivamente lidos DX+2 =Início dos caracteres lidos. O fim da string é marcado pelo caracter CR (0Dh) 7. Função 0Bh Devolve o valor FFh no registrador AL se houver um caracter no buffer do teclado pronto a ser lido. Se AL=00, não existe caracter no buffer do teclado. Entrada: AH=0Bh Saída: AL 8. Função 0Ch Esta função limpa o buffer do teclado, preparando-o para a execução de qualquer outra função de teclado. Desta forma, em AL deve-se ter o valor da nova função a ser executada (1,6,7,8 ou 0Ah). Entrada: (a) AH=0Ch (b) AL=número de uma função de teclado Saída: nenhuma 9. Função 25h Esta função é utilizada para alterar o valor de um vetor de interrupção. Entrada (a) AH=25h (b) AL = número da interrupção (c) DS:DX = novo vetor da interrupção Saída: Nenhuma 4
10. Função 2Ah Devolve a data atual nos registradores CX e DX. O dia da semana é devolvido em AL, como um valor de 0 a 6, indicando os dias da semana de domingo a sábado. Entrada: AH=2Ah Saída: (a) DH = Número do mês (1 a 12) (b) DL = Número do dia (1 a 31) (c) CX = Número do ano (1980 a 2099) (d) AL= dia da semana 11. Função 2Bh Muda a data do sistema. Esta função retorna em AL um valor de 0 a 6, indicando o dia da semana correspondente àquela data. Entrada: (a) AH=2Bh (b) DH=número do mês (c) DL=número do dia (d) CX=número do ano Saída: se AL=FFh existe um erro na data ou AL=número de 0 a 6, indicando o dia da semana 12. Função 2Ch Devolve a hora atual do sistema nos registradores CX e DX Entrada: AH=2Ch Saída: (a) CH=hora (0 a 23) (b) CL=minutos(0 a 59) (c) DH=segundos(0 a 59) (d) DL=Centésimos de segundo(0 a 99) 13. Função 2Dh Fixa a hora do sistema, utilizando os valores de CX e DX Entradas: (a) AH=2Dh (b) CH=hora (0 a 23) (c) CL=minutos(0 a 59) (d) DH=segundos(0 a 59) (e) DL=centésimos de segundo (0 a 99) Saída: se AL=FFh, erro na hora. Se AL=00, operação realizada. 5
14. Função 35h Retorna o vetor de interrupção especificado pelo número em AL. Esta função é utilizada para salvar o endereço de rotina de interrupção, antes de alterar o vetor de interrupção. Entrada: (a) AH=35h (b) AL=número da interrupção Saída: ES:BX=vetor da interrupção 15. Função 4Ch Esta função encerra um programa, fechando automaticamente todos os arquivos que porventura tenham sido criados ou abertos e devolve um código de retorno ao programa chamador ou ao DOS. Entrada: (a) AH=4Ch (b) AL=código de retorno (opcional) Saída: nenhuma 1.2 Exemplos de programas A seguir serão mostrados algums exemplos utilizando as interrupções do DOS. comment *Programa exemplo da funcao 01 do DOS. Este programa aguarda a digitacao de uma tecla, ecoando-a na tela.o programa, entao, soma 10 a tecla digitada armazenandoo resultado em BL. Nao existe nenhum teste para ver se a tecla e um numero.* mov ah,1 ;prepara para chamar a funcao 01 do DOS ;chama a funcao do DOS. Esta funcao aguarda o usuario digitar ;uma tecla, ecoando-a na tela. A tecla digitada retorna em AL sub al, 30h ;subtrai 30h para converter de um codigo ASCII para um ;valor numerico mov bl, al add bl,10 ;BL contem o resultado da tecla digitada acrescida de 10. ;prepara para indicar fim de programa ;Sinaliza fim de programa 6
comment *Programa exemplo da funcao 01 do DOS faz a mesma coisa que o programa anterior, porem utilizando chamada de procedimento* digito proc near mov ah,1 sub al, 30h mov bl, al add bl,10 ret digito endp call digito ;chama o procedimento ;ao retornar do procedimento BL contera o resultado da ;tecla digitada acrescida de 10 ;prepara para indicar fim de programa ;Sinaliza fim de programa 7
comment *Programa exemplo da funcao 02 do DOS. Este programa imprime na tela o texto TST, muda de linha e imprime o texto 2, caractere por caractere* mov ah,2 mov dl, T mov dl, S mov dl, T mov dl,10 mov dl,13 mov DL, 2 ;prepara para chamar a funcao 02 do DOS ;primeiro caractere a ser mostrado na tela ;chama a funcao do DOS, mostrando o caractere. ;segundo caractere a ser mostrado na tela ;chama a funcao do DOS, mostrando o caractere. ;terceiro caractere a ser mostrado na tela ;chama a funcao do DOS, mostrando o caractere. ;Muda de linha, caractere de LF ;chama a funcao do DOS, mostrando o caractere. ;Retorna o cursor para o comeco da linha(cr) ;chama a funcao do DOS, mostrando o caractere. ;Primeiro caractere da segunda linha ;chama a funcao do DOS, mostrando o caractere. ;prepara para indicar fim de programa ;Sinaliza fim de programa 8
comment *Programa exemplo da funcao 09 do DOS. Este programa imprime na tela o texto Interrupcoes do DOS, muda de linha e imprime o texto Teste da funcao 09 * texto1 db Interrupcoes do DOS$ texto2 db Teste da funcao 09$ mudalinha db 10,13, $ mov ah,9 ; prepara para chamar a funcao 09 do DOS lea dx,texto1 ;faz com que DX aponte para a string a ser ;mostrada na tela ;mov dx, offset texto1 ;esta linha faz a mesma coisa da linha anterior, ;repare no comentario do comeco da linha ;chama a funcao do DOS, mostrando a string lea dx,mudalinha lea dx, texto2 ;manda os caracteres de controle para mudanca ;de linha ;chama a funcao do DOS, mostrando a string ;prepara para mostrar na tela a segunda linha ;chama a funcao do DOS, mostrando a string ;prepara para indicar fim de programa ;Sinaliza fim de programa comment *Programa exemplo da funcao 09 do DOS. Este programa faz a mesma coisa do exemplo anterior, porem utilizando apenas uma variavel * texto db Interrupcoes do DOS, 10, 13, Teste da funcao 09$ mov ah,9 lea dx,texto ;prepara para chamar a funcao 09 do DOS ;faz com que DX aponte para a string a ser ;mostrada na tela ;chama a funcao do DOS, mostrando a string ;prepara para indicar fim de programa ; Sinaliza fim de programa 9
comment *Programa exemplo da funcao 0A do DOS. Este programa espera o usuario digitar uma string de ate 10 caracteres e, apos digitada, repete a string na tela* digitada db 14 dup( $ ) ;reserva o espaco de memoria para armazenar a ;string digitada, ja preenchendo com o marcador ; de fim de string texto db 10,13, A string digitada foi: $ lea si, digitada mov bl, 11 mov [si], bl mov AH, 0Ah lea dx, digitada mov ah,9 lea dx,texto mov ah,9 lea dx, digitada add dx, 2 ;faz com que SI aponte para a variavel que ira armazenar ;a string ;o primeiro byte da variavel tem que conter a quantidade ;maxima de caracteres ;que serao recebidos deve-se considerar a tecla enter ;Prepara para chamar a funcao 0A ;DX aponta para a string que ira armazenar os dados ;digitados ;chama a funcao do DOS ;prepara para chamar a funcao 09 do DOS ;DX aponta para a string a ser mostrada na tela ;chama a funcao do DOS, mostrando a string ;prepara para chamar a funcao 09 do DOS, para mostrar ;a string digitada ;DX aponta para o primeiro byte da variavel ;agora DX aponta para a posicao de memoria que contem ;a primeira tecla digitada ;chama a funcao do DOS, mostrando a string na tela ;prepara para indicar fim de programa ;Sinaliza fim de programa 10
comment *Programa exemplo de rotinas. Este programa imprime na tela uma string seguida pelo conteudo do registrador BL.* texto db 10,13, Numero contido no registrador BL: $ BIN2ASCII proc near comment *rotina para converter um numero decimal (contido em BL) para um ASCII. O maior numero possivel de ser convertido por esta rotina é 99.* mov bh,0 COMPARA: ;somente um label, nao é um comando cmp bl,10 jl fimconverte sub bl,10 inc bh jmp compara FIMCONVERTE: ;somente um label, nao é um comando add bx,3030h ret endp lea dx, texto mov ah,09 mov bl, 20 call BIN2ASCII mov ah,2 mov dl,bh mov dl,bl ;chama a rotina de conversao ;os dois digitos apos a conversao estao em BH e BL ; prepara para chamar a funcao 02 do DOS ; digito das dezenas ; chama a funcao do DOS, mostrando o caractere. ; digito das unidades ; chama a funcao do DOS, mostrando o caractere. 2 Parte Experimental : 1. Desenvolva um programa para pergunte ao usuário se ele quer mostrar ( S/N ) a data/hora do sistema na tela. Caso o usuário escolha S, o programa deverá, então,mostrar na tela a data e hora corrente do sistema, no formato: hh:mm - dd/mm - dia da semana (sem as aspas duplas), por exemplo: 08:25-13/03 - segunda-feira Não é necessário mostrar o ano corrente. Caso o usuário escolha N, o programa deverá simplesmente deixar de ser executado e nada deverá aparecer na tela. Pode-se optar por mostrar o nome completo do dia da semana (segunda-feira), ou apenas parte deste, com três letras (seg). 11
3 Anexo A - Tabela ASCII A tabela ASCII (American Standard Code for Information Interchange) foi originalmente criada para teletipos e, portanto, a descrição de alguns de seus caracteres, atualmente, não tem o mesmo significado. Entretanto, ela ainda é amplamente utilizada hoje em dia. Decimal Hex Valor Descrição Decimal Hex Valor Decimal Hex Valor 0 0 NUL Null char. 42 02A * 85 55 U 1 1 SOH Start of Header 43 02B + 86 56 V 2 2 STX Start of Text 44 02C, 87 57 W 3 3 ETX End of Text 45 02D - 88 58 X 4 4 EOT End of Transmission 46 02E. 89 59 Y 5 5 ENQ Enquiry 47 02F / 90 05A Z 6 6 ACK Acknowledgment 48 30 0 91 05B [ 7 7 BEL Bell 49 31 1 92 05C \ 8 8 BS Backspace 50 32 2 93 05D ] 9 9 HT Horizontal Tab 51 33 3 94 05E 10 00A LF Line Feed 52 34 4 95 05F 11 00B VT Vertical Tab 53 35 5 96 60 12 00C FF Form Feed 54 36 6 97 61 a 13 00D CR Carriage Return 55 37 7 98 62 b 14 00E SO 56 38 8 99 63 c 15 00F SI 57 39 9 100 64 d 16 10 DLE Data Link Escape 58 03A : 101 65 e 17 11 DC1 XON-Dev. Control 1 59 03B ; 102 66 f 18 12 DC2 Device Control 2 60 03C < 103 67 g 19 13 DC3 XOFF-Dev. Control 3 61 03D = 104 68 h 20 14 DC4 Device Control 4 62 03E > 105 69 i 21 15 NAK Negative Acknowl. 63 03F? 106 06A j 22 16 SYN Synchronous Idle 64 40 @ 107 06B k 23 17 ETB End of Trans. Block 65 41 A 108 06C l 24 18 CAN Cancel 66 42 B 109 06D m 25 19 EM 67 43 C 110 06E n 26 01A SUB 68 44 D 111 06F o 27 01B ESC Escape 69 45 E 112 70 p 28 01C FS File Separator 70 46 F 113 71 q 29 01D GS 71 47 G 114 72 r 30 01E RS Request to Send 72 48 H 115 73 s 31 01F US 73 49 I 116 74 t 32 20 SP Space 74 04A J 117 75 u 33 21! 75 04B K 118 76 v 34 22 76 04C L 119 77 w 35 23 # 77 04D M 120 78 x 36 24 $ 78 04E N 121 79 y 37 25 % 79 04F O 122 07A z 38 26 & 80 50 P 123 07B { 39 27 81 51 Q 124 07C 40 28 ( 82 52 R 125 07D } 41 29 ) 83 53 S 126 07E 84 54 T 127 07F DEL 12