2016-04-11 56 views
5

Voglio interrompere l'esecuzione di circa 0,1 secondi, indipendentemente dalla velocità di clock della CPU. Il codice dovrebbe essere eseguito direttamente da un dispositivo di avvio, pertanto non dovrebbe utilizzare gli interrupt DOS.Come dormire nell'assemblaggio x86 a 16 bit in metallo nudo?

Attualmente sto usando int 15h, ma questo sembra essere in conflitto con i segnali acustici che sto modulando con il canale 2 del PIT. Ho sentito parlare del canale 0, ma non ho idea di come impostarlo.

L'accuratezza non è così importante, tuttavia, dovrebbe funzionare su computer vecchi e moderni alla stessa velocità. Quindi le istruzioni di looping non sono un'opzione.

Il codice bip e il sonno sono solo un mucchio di macro per cambiare la frequenza e accendere e spegnere l'altoparlante. Il segnale acustico sembra non fermarsi se chiamo sleep prima dello beepoff.

Qui ci sono le macro colpo di clacson:

%macro beepinit 0 
    mov al, 182 
    out 43h, al 
%endmacro 

%macro beepfreq 0 
    out 42h, al 
    mov al, ah 
    out 42h, al 
%endmacro 

%macro beepon 0 
    in al, 61h 
    or al, 00000011b 
    out 61h, al 
%endmacro 

%macro beepoff 0 
    in al, 61h 
    and al, 11111100b 
    out 61h, al 
%endmacro 

e il sonno uno:

%macro sleep 2 
    push dx 
    mov ah, 86h 
    mov cx, %1 
    mov dx, %2 
    int 15h 
    pop dx 
%endmacro 

sto usando l'assembler NASM.

Questo non è un duplicato di How can I create a sleep function in 16bit MASM Assembly x86?, perché questo è per l'assemblaggio bare metal all'esterno di Windows o DOS.

+1

Vorrei suggerire di rendere il titolo "Come dormire nell'assemblaggio x86 a 16 bit in metallo nudo" per distinguere le domande da quella dipendente dal sistema operativo. Forse indicando nella domanda come si è tentato di usare int 15h si potrebbe aiutare la domanda a non essere troppo ampia (è borderline nella sua forma attuale). –

+0

@PascalCuoq Ok, l'ho modificato un po '. –

+0

Correlati: http://stackoverflow.com/a/1862232/509868 – anatolyg

risposta

3

Il timer di intervallo programmabile è la strada da percorrere. Se si affronteranno solo i sistemi più recenti, consultare HPET. Per PIT ci sono alcune cose da sapere. In primo luogo, per configurarlo è necessario utilizzare la porta 0x43 come porta di controllo/comando per configurare il timer dello zero del canale. Il byte che vogliamo mandare è presente un campo mappato po ':

7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 
+----------------------------------------------+ 
| Channel | RW Mode | Channel Mode | BCD?| 
+----------------------------------------------+ 

canale verrà cancellato per selezionare il canale zero.

Il modello RW può essere 1-LSB, 2-MSB o 3-LSB seguito da MSB. Vogliamo entrambi i bit su (bit pattern di 3, 011) perché dobbiamo inviare un valore a 16 bit (LSB e MSB)

Per la modalità di canale vogliamo un'onda quadra. Questo è un modello bit di 3 (011)

Vogliamo inviare un divisore a 16 bit per il contatore, non un valore BCD, quindi il bit più basso viene cancellato.

Questo ci dà: 000110110 in binario o 0x36 in esadecimale. Ora abbiamo impostato su:

mov al, 0x36 ; 0x36 from our work above 
out 0x43, al ; Send that byte to the control port 

mov ax, 11931 ; The timer ticks at 1193182. 100hz would be 1193182/11931 
out 0x40, al ; send low byte 
out 0x40, ah ; send high byte 

A questo punto è necessario decidere se si sta andando a reagire ad un interrupt (IRQ 0) o semplicemente desidera leggere il timer. Ti indicherò su this excellent reference su OSDev che ha una brillante scrittura su entrambi con codice di esempio.

+0

Il problema è che il codice di esempio su OSDev è fatto per l'assembly a 32 bit. –

+0

... perché questo è un problema? È piuttosto semplice tradurre questo a 16 bit o, in alternativa, lasciare gli interrupt del BIOS dietro e andare in modalità protetta. –

+0

Ad esempio, con il codice che ho postato qui (tutti i 16 bit) è possibile leggere periodicamente il canale zero per ottenere il conteggio delle transizioni o impostare un ISR per IRQ 0. Nulla cambia realmente tra il codice 32 e 16 bit fino a questo va tranne la dimensione degli indirizzi. –