Atividade 4: Entrada/saída com "embedded assembly"
e Rotinas de Interrupção
O objetivo desta atividade é utilizar a técnica de "embedded
assembly" para escrever rotinas de interrupção
e controlar dispositivos de entrada/saida de um PC e também codificar
em assembler uma rotina de interrupção completa.
1. Re-escreva o programa inhand.c
visto em aula para:
-
salvar o atual vetor de interrupção, instalar uma nova rotina
de interrupção e no final restaurar o vetor de interrupção
original,
-
todo o corpo da rotina de interrupção deve ser escrito em
"embedded assembly",
-
ela deve emitir cerca de oito tons com duração de um a dois
segundos cada um;
-
ela deve emitir mensagem para o vídeo dizendo a frequencia
do tom sendo emitido.
Observações:
-
Para compilar um programa em C contendo instruções em assembler
use o comando: tcc -B nomeprog.c
-
Para salvar o vetor de interrupção n utilize a função:
oldint=
getvect(n)onde
oldint deve ser uma variável do tipo
"apontador para rotina de
interrupção", isto é: void interrupt ( *oldint)()
-
para instalar um novo vetor de interrupção utilize a função
setvect
(n, faddr), vista em aula
-
a função em C outportb(num_porta, valor_8bits)
corresponde à instrução em assembler: out
num_porta, al
-
a função em C inportb(num_porta) corresponde
à instrução em assembler: in al, num_porta
-
dado um valor codfreq com o código da freqüência
de um tom, codfreq/2 duplica a freqüência e codfreq*2 divide
a freqüência por 2.
-
Para ajustar a duração do tom do alto-falante (em segundos)
de forma independente da velocidade da CPU V. deve usar a rotina
delay
incluída
no exemplo delay.asm
visto em aula. V. precisa mudá-la, no entanto, porque o "inline
assembly" será montado pelo tasm da Borland (e não
pelo nasm) e o tasm não aceita o uso dos registradores
de 32 bits do 386+ (eax e ebx), mas V. pode (opcionalmente pois
há uma pequena chance de dar errado!) trabalhar apenas com os 16
bits menos significativos do contador do Relógio de Tempo Real.
Outra diferença é que o acesso a uma posição
de memória pelo seu endereço numérico tem uma sintaxe
diferente no tasm: para ler os 16 bits menos significativos do contador
V. deve usar no seu "inline assembly" a instrução: asm
mov reg16, ds:word ptr 046ch .
Sugestões:
-
Insira o código da rotina delay.asm diretamente na rotina de interrupção
no ponto onde há os loops de espera em C ("in-line")
-
Freqüências razoavelmente audíveis num PC vão
de 60 hz a 9000 hz.
-
Use a função INT 21h, 09h do DOS para emitir as mensagens
no vídeo de forma semelhante à vista nos exemplos como em
myarray.c
-
Se houver erro emitido pelo tasm (que indica as linhas onde ocorreu
erro) edite o arquivo gerado, nomeprog.asm, e observe
a linha em que o erro foi acusado. Em geral é simples identificar
imediatamente o erro.
2. Escreva um programa inteiramente em assembler que:
-
instala uma rotina de interrupção para interceptar uma divisão
por zero (cujo número de interrupção é 0),
-
executa uma instrução de divisão que gera uma interrupção
de número 0,
-
ao interceptar a divisão por zero feita pelo programa, a rotina
de interrupção deve emitir uma mensagem do tipo "V. tentou
dividir por zero!" (use a função INT 21h, 09 do DOS ).
Obs: a fim de evitar que seu programa entre num laço
infinito de interrupções, a rotina de interrupção
deve retornar com o IP apontando para a instrução seguinte
àquela que fez a divisão por zero.
-
Seu programa deve emitir uma mensagem antes da instrução
de dividir por zero, a mensagem acima emitida pela rotina de interrupção
e outra mensagem após o retorno da rotina de interrupção.
V. deve demonstrar o funcionamento dos dois programas no laboratório
e entregar uma impressão do programa em C e do programa em
assembler (no formato .lst)
Data de submissão: 22/04/02 Prazo de Entrega: 15/05/02.