
L'accesso all'I/O, con la scusa del beep
Se occorre inviare un beep all'operatore, tramite la console, e' sufficiente inviare in output il carattere BEL, codice Ascii 07h, come nel semplicissimo esempio sottostante.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; beep_1.asm
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;compilare con nasm+gcc
global main ;necessario per il linker gcc
extern printf
section .data
beep db 07h,0
section .text
main:
push dword beep ;Passa il Ptr Stringa
call printf
add esp,4 ;Riallinea lo Stack
ret
;EOF ::::::::::::::::::::::::::::::::::::::
Ma se non ci accontentiamo del segnale acustico predefinito e ne vogliamo uno di frequenza e durata variabili ? A questo punto risulta evidente che il beep e' la scusa per parlare di I/O. Per raggiungere l'obiettivo faremo uso del terzo timer programmabile presente nell'8253 che fara' giungere un segnale alla frequenza desiderata all'altoparlante, che verra' abilitato tramite l'8255. Tutto fattibile, se il controllo dell'hardware fosse sotto il nostro totale controllo. Eppure la possibilita' esiste, basta chiedere il permesso al S.O. per lavorare a livello di root. Pertanto il nostro esempio, su macchine Intel compatibili, realizzera' i seguenti punti:
Il listato e' abbastanza lineare, ma alcuni passaggi richiedono la conoscenza dei byte di programmazione per l'8253 e le connessioni hardware tra 8255, 8253 ed altoparlante.
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; beep_2.asm
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;compilare con nasm+gcc
%macro @ioperm 3
mov ebx,%1 ;;Numero porto iniziale;
mov ecx,%2 ;;Quantita' di porti in successione
mov edx,%3 ;;Richiesta: 1=Abilitazione, 0=Revoca
mov eax,101 ;;Funzione sys_call=ioperm
int 80h
or eax,eax ;;Test esito: "jns okay"
%endmacro
global main ;necessario per il linker gcc
extern usleep, printf
section .data
msgerr db "NON abilitato all'uso dei porti di I/O! "
db "Occorrono i privilegi di ROOT.",0Ah
db "Oppure si e' verificato un ERRORE nel caso "
db "si sia in ROOT.",7,0Ah,0
durata dd 200000
section .text
main: @ioperm 61h,1,1 ;Richiesta Permesso 8255 I/O 61h
jns okay1
jmp err
okay1: @ioperm 42h,2,1 ;Richiesta Permesso 8253 I/O 42h e 43h
jns okay2
jmp err
okay2: in al,61h ;Abilita altoparlante
or al,3
out 61h,al
mov al,0B6h ;Programmazione timer 8253
out 43h,al
mov ax,0800h ;Impostazione costante di frequenza
out 42h,al
mov al,ah
out 42h,al
push dword [durata] ;Imposta durata in microsecondi
call usleep
add esp,4 ;Riallinea lo Stack
in al,61h ;Disabilita altoparlante
and al,0FCh
out 61h,al
jmp exit
err: push dword msgerr ;Passa il Ptr Stringa
call printf
add esp,4 ;Riallinea lo Stack
exit: @ioperm 42h,2,0 ;Revoca Permessi I/O
@ioperm 61h,1,0
ret
;EOF :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Lo schema seguente aiuta a capire alcuni passaggi relativi alle istruzioni di in e di out presenti nel programma. Come si vede, l'uscita dell'altoparlante e' condizionata sia dal segnale di out dell'8253 sia dal bit 1 del porto B 8255. A sua volta l'8253 viene abilitato al suo gate dal bit 0 del porto B 8255. Pertanto e' necessario che i 2 bit 0,1 del porto B 8255 siano alti per abilitare l'uscita del segnale sull'altoparlante (vedi or al,3), e siano invece bassi per bloccare il segnale (vedi and al,0FCh) alla fine.
![]() |
Mentre la programmazione del timer avviene in due fasi. Prima viene fissato il modo operativo dell'8253 tramite il Registro di controllo che ha sede nel Porto 43h; per funzionare come generatore di frequenza occorre inviare il byte B6h (vedi documentazione Intel). Quindi, per fissare la frequenza di funzionamento, viene inviata una word tramite il Porto 42h, e cio' si realizza con due operazioni di out, un byte alla volta.

Menù

Insegnare è imparare due volte.
Joseph Joubert