2010-07-09 14 views
41

Ho consultato queste istruzioni per le istruzioni IN & OUT durante la lettura del libro "Capire il kernel di Linux". Ho consultato il manuale di riferimento.Quali sono le istruzioni IN & OUT in x86 utilizzate?

5.1.9 Istruzioni di I/O

queste operazioni di trasferimento dei dati tra porte di I/O del processore e un registro o memoria.

IN Read from a port 
OUT Write to a port 
INS/INSB Input string from port/Input byte string from port 
INS/INSW Input string from port/Input word string from port 
INS/INSD Input string from port/Input doubleword string from port 
OUTS/OUTSB Output string to port/Output byte string to port 
OUTS/OUTSW Output string to port/Output word string to port 
OUTS/OUTSD Output string to port/Output doubleword string to port 

non ho avuto alcune cose:

  1. "porte I/O del processore". Quali sono? Perché dovremmo leggere & scrivere "stringhe" su & da queste porte?
  2. Non ho mai scoperto uno scenerio dove ho bisogno di usare queste istruzioni. Quando avrei bisogno di questi?
  3. Fornire alcuni esempi pratici.

risposta

62

Sai come funziona l'indirizzamento della memoria? C'è un bus indirizzo, un bus dati e alcune linee di controllo. La CPU inserisce l'indirizzo di un byte (o un byte di inizio) della memoria sul bus di indirizzo, quindi solleva il segnale READ e qualche chip RAM restituisce il contenuto della memoria a quell'indirizzo alzando o abbassando le singole righe (corrispondenti ai bit nei byte) sul bus dati. Funziona sia per RAM che per ROM.

Ma poi ci sono anche dispositivi I/O: porte seriali e parallele, il driver per il minuscolo altoparlante interno di un PC, i controller del disco, i chip audio e così via. E anche questi dispositivi vengono letti e scritti da. Devono inoltre essere indirizzati in modo che la CPU acceda al dispositivo corretto e (di solito) alla corretta posizione dei dati all'interno di un determinato dispositivo.

Per alcuni modelli di CPU, inclusa la serie xxx86, presente nella maggior parte dei PC "moderni", i dispositivi I/O condividono lo spazio indirizzo con la memoria. Entrambi i dispositivi RAM/ROM e IO sono collegati allo stesso indirizzo, ai dati e alle linee di controllo. Ad esempio, la porta seriale per COM1 viene indirizzata a partire da (hex) 03F8. Ma c'è quasi certamente memoria allo stesso indirizzo.

Ecco uno schema molto semplice:

[https://qph.ec.quoracdn.net/main-qimg-e510d81162f562d8f671d5900da84d68-c?convert_to_webp=true]

Chiaramente la CPU ha bisogno di parlare con memoria o il dispositivo di I/O, mai entrambe. Per distinguere tra i due, una delle linee di controllo chiamata "M/# IO" asserisce se la CPU vuole parlare alla memoria (riga = alta) o un dispositivo I/O (linea = bassa).

L'istruzione IN viene letta da un dispositivo I/O, scritture OUT. Quando si usano le istruzioni IN o OUT, il M/# IO non viene asserito (tenuto premuto), quindi la memoria non risponde e il chip I/O lo fa. Per le istruzioni orientate alla memoria, M/# IO viene asserito in modo che la CPU parli alla RAM e gli IO Device rimangano fuori dalla comunicazione.

In determinate condizioni i dispositivi IO possono pilotare le linee dati e la RAM può leggerle contemporaneamente. E viceversa. Si chiama DMA.

Tradizionalmente, le porte seriali e della stampante, oltre a tastiera, mouse, sensori di temperatura e così via erano dispositivi I/O.I dischi erano una specie di mezzo; i trasferimenti di dati verrebbero avviati dai comandi di I/O, ma il controller del disco di solito li depositerebbe direttamente nella memoria di sistema.

Nei moderni sistemi operativi come Windows o Linux, l'accesso alle porte I/O è nascosto da "normali" programmi utente, e ci sono strati di software, istruzioni privilegiate e driver per gestire l'hardware. Quindi, in questo secolo, la maggior parte dei programmatori non si occupa di quelle istruzioni.

+0

Potete consigliare un libro dove posso leggere di più su questo? la tua risposta è grande, grazie! –

+0

Penso di aver imparato per lo più questa roba in un corso di architettura informatica presso la mia università, circa 30 anni fa; quindi non posso citare un libro da cui ho preso questa roba, scusa! Tuttavia, su Google google per alcune parole chiave pertinenti, ho trovato molti di loro in una pagina in un libro: http://www.amazon.com/Microprocessors-Microcomputer-Based-System-Mohamed-Rafiquzzaman/dp/0849344751 I non posso dirti nulla del libro se non che è del 1995 e non potrei vedermi pagare $ 149 per questo. Il tuo chilometraggio può variare, ovviamente. –

+0

Ben fatto. Grazie per questa spiegazione. Sono stato a lungo confuso dalla nozione di IO spazio come mi è stato insegnato rigorosamente con MMIO. Il fatto che memoria e IO possano essere pensati come indirizzabili a loro stessi mi lascia un po 'imbarazzato per non averlo capito prima. – sherrellbc

0

CPU collegata ad alcuni controller esterni tramite porte io. sul vecchio x86 pc lavoro con unità floppy usando le porte I/O. se sai quali comandi accettano il controller del dispositivo, puoi programmarlo attraverso le sue porte.

Nel mondo moderno non si useranno mai le istruzioni per le porte. Eccezione se sei (o lo sarai) sviluppatore di driver.

ci sono informazioni più dettagliate su porte I/O http://webster.cs.ucr.edu/AoA/DOS/ch03/CH03-6.html#HEADING6-1

3

Se non stai scrivendo un sistema operativo, allora non sarà mai utilizzare queste istruzioni I.

Le macchine basate su x86 hanno due spazi di indirizzi indipendenti: lo spazio degli indirizzi di memoria che si ha familiarità con lo spazio degli indirizzi I/O. Gli indirizzi delle porte I/O sono solo 16 bit di larghezza e i registri di basso livello di riferimento e altri widget di basso livello che fanno parte di un dispositivo I/O, qualcosa come una porta seriale o parallela, controller del disco, ecc.

Non ci sono esempi pratici perché questi sono usati solo dai driver di dispositivo e dai sistemi operativi.

+5

Se stai scrivendo autisti possono certamente essere usati. – Jay

+0

http://webster.cs.ucr.edu/AoA/DOS/ch03/CH03-1.html#HEADING1-76 – claws

+1

@Downvoter: quindi perché non dici alle persone qual è il problema? –

3

A livello hardware, la maggior parte dei microprocessori ha poca o nessuna capacità di I/O integrata. Alcuni processori hanno uno o più pin che possono essere accesi e spenti utilizzando istruzioni speciali e/o uno o più pin che possono essere testato utilizzando istruzioni speciali per le filiali, ma tali funzionalità sono rare. Invece, l'I/O viene solitamente gestito collegando il sistema in modo che l'accesso a un intervallo di indirizzi di memoria possa innescare qualche effetto, o includendo istruzioni "in" e "out" che si comportano come operazioni di caricamento/memorizzazione della memoria eccetto che un segnale speciale viene visualizzato dicendo "Questa è un'operazione di I/O invece di un'operazione di memoria". Ai tempi dei processori a 16 bit, c'erano dei veri vantaggi nell'avere istruzioni specialistiche in/out. Oggigiorno tali vantaggi sono in gran parte discutibili, dal momento che si può semplicemente allocare una grande porzione del proprio spazio di indirizzamento all'I/O e ne rimane ancora abbastanza per la memoria.

Poiché un programma può provocare considerevoli danni su un sistema eseguendo in modo inappropriato le istruzioni di I/O (ad esempio, tali istruzioni potrebbero eseguire accessi al disco arbitrari), tutti i sistemi operativi moderni vietano l'uso di tali istruzioni nel codice a livello utente. Alcuni sistemi possono consentire la virtualizzazione di tali istruzioni; se il codice utente tenta di scrivere su porte I/O 0x3D4 e 0x3D5, ad esempio, un sistema operativo potrebbe interpretarlo come un tentativo di impostare alcuni registri di controllo del controllo video per spostare il cursore lampeggiante. Ogni volta che il programma utente eseguiva l'istruzione OUT, il sistema operativo prendeva il sopravvento, verificava cosa stava cercando di fare il programma utente e agiva in modo appropriato.

Nella maggior parte dei casi, anche se il sistema operativo traducesse un'istruzione IN o OUT in qualcosa di adatto, sarebbe più efficiente richiedere direttamente l'azione appropriata dal sistema operativo.

22

Inizia con qualcosa di simile:

http://www.cpu-world.com/info/Pinouts/8088.html

State imparando le istruzioni per un tempo molto vecchia tecnologia dei chip/architettura. Indietro quando tutto tranne il core del processore era off-chip.Vedi le linee di indirizzo e le linee di dati e c'è una riga di lettura RD e riga di scrittura WR e linea IO/M?

Esistono due tipi di istruzioni basate sulla memoria e I/O in base al fatto che c'erano spazi indirizzabili, facilmente decodificati dall'IO/M IO o dalla memoria.

Ricordate che la logica di incollaggio 74LSxx, molti fili e molti chip per collegare una memoria al processore. E la memoria era solo quel ricordo, grandi chip costosi. Se avessi una periferica necessaria a fare qualcosa di utile, avevi anche i registri di controllo, la memoria potrebbe essere i dati dei pixel, ma da qualche parte dovevi impostare i limiti di scansione orizzontale e verticale, questi potrebbero essere singoli latch 74LSxx, NON ricordi, avere io/O mappato I/O salvato su entrambe le logiche di colla e ha molto senso dal punto di vista del programmatore, evitando anche di cambiare i registri dei segmenti per mirare alla finestra della memoria 64K, ecc. Lo spazio degli indirizzi di memoria era una risorsa sacra, specialmente quando volevo limitare la decodifica dell'indirizzo a pochi bit perché ogni bit costava un certo numero di chip e fili.

Come l'I/O mappato I/O mappato in memoria I/O big e little endian era una guerra religiosa. E alcune delle risposte che vedrai alla tua domanda rifletteranno le opinioni forti che sono ancora in circolazione oggi nelle persone che l'hanno vissuta. La realtà è che ogni chip sul mercato oggi ha più busess per varie cose, non si blocca il tuo orologio in tempo reale dal bus di memoria ddr con un decodificatore di indirizzi. Alcuni hanno persino bus di dati e istruzioni completamente separati. In un certo senso, Intel ha vinto la guerra per il concetto di spazi di indirizzi separati per diverse classi di cose anche se il termine porta I/O è malvagio e cattivo e non dovrebbe essere pronunciato per dire 20-30 anni in più. Hai bisogno della gente della mia età che l'abbia vissuta per essere ritirata o scomparsa prima che la guerra sia davvero finita. Anche il termine I/O mappato in memoria è una cosa del passato.

Questo è davvero tutto ciò che è sempre stato, un singolo indirizzo decodifica un bit all'esterno del chip Intel che è stato controllato mediante l'uso di istruzioni specifiche. Usa un set di istruzioni in cui il bit era in uso una serie di istruzioni che il bit era spento. Vuoi vedere qualcosa di interessante da un'occhiata al set di istruzioni per i processori xmos xcore hanno un sacco di cose che sono istruzioni invece di registri mappati in memoria, ci vuole questo I/O mappato I/O cosa ad un livello completamente nuovo.

Dove è stato utilizzato è come descritto sopra, si inserirebbero cose che avevano senso e si poteva permettersi di masterizzare lo spazio di indirizzamento della memoria per pixel video simili, memoria di pacchetti di rete (forse), memoria di schede audio (beh non sia ma si potrebbe avere), ecc. E i registri di controllo, lo spazio di indirizzamento relativo ai dati era molto piccolo, forse solo pochi registri, sono stati decodificati e utilizzati nello spazio I/O. le ovvie sono/erano le porte seriali e le porte parallele che avevano poca o nessuna memoria, avresti potuto avere un piccolo fifo sulla porta seriale se non altro.

Perché lo spazio indirizzo era scarso non era raro ed è ancora visto oggi di avere la memoria nascosta dietro due registri un registro indirizzo e di un registro di dati, questa memoria è disponibile solo attraverso questi due registri, non è la memoria mappata. quindi scrivi l'offset in questa memoria nascosta nel registro degli indirizzi e leggi o scrivi il registro dei dati per accedere al contenuto della memoria. Ora perché intel aveva le istruzioni rep e si poteva combinarlo con insb/w outsb/w il decodificatore hardware sarebbe (se tu avessi gente simpatica/amichevole che lavora con te) autoincrementare l'indirizzo ogni volta che hai fatto un ciclo I/O. Quindi è possibile scrivere l'indirizzo di partenza nel registro degli indirizzi e fare un rep outsw e senza masterizzare i cicli di fetch e decode clock nel processore e sul bus di memoria si potrebbe spostare i dati abbastanza velocemente dentro o fuori dalla periferica. Questo genere di cose è ora considerato un difetto di progettazione grazie ai moderni processori super scalari con recuperi basati sulla previsione delle filiali, l'hardware può leggere in qualsiasi momento senza avere nulla a che fare con l'esecuzione del codice, pertanto non è MAI necessario incrementare automaticamente un indirizzare o cancellare i bit in un registro di stato o modificare qualcosa come risultato di una lettura in un indirizzo.

I meccanismi di protezione incorporati nel 386 e al presente rendono davvero molto facile l'accesso I/O dallo spazio utente. A seconda di cosa fai per vivere, cosa produce la tua azienda, ecc. Puoi sicuramente usare la famiglia di istruzioni dallo spazio utente (programmi applicativi in ​​windows e linux, ecc.) O spazio kernel/driver, è il tuo scelta. Puoi anche fare cose divertenti come approfittare della macchina virtuale e usare le istruzioni I/O per parlare con i driver, ma questo probabilmente farebbe incazzare la gente sia nei mondi windows che linux, che driver/app non lo farebbero molto lontano. Gli altri poster sono corretti in quanto probabilmente non avrai mai bisogno di usare queste istruzioni a meno che tu non stia scrivendo i driver, e probabilmente non scriverai mai driver per dispositivi che usano I/O mappato I/O perché sai ... il i driver per questi dispositivi legacy sono già stati scritti. I progetti moderni hanno sicuramente I/O ma sono tutti mappati in memoria (dal punto di vista dei programmatori) e utilizzano istruzioni di memoria e non istruzioni I/O. Ora il lato opposto se questo è DOS non è sicuramente morto, a seconda di dove potresti costruire macchine per il voto o pompe di benzina o registratori di cassa o una lunga lista di apparecchiature basate su DOS. Infatti, se lavori da qualche parte per la costruzione di periferiche o schede madri PC o PC, gli strumenti basati su DOS sono ancora ampiamente utilizzati per testare e distribuire aggiornamenti del BIOS e altre cose simili. Mi imbatto ancora in situazioni in cui devo prendere il codice da un programma di test DOS corrente per scrivere un driver linux. Proprio come non tutti quelli che possono lanciare o prendere una partita di football nella NFL, la percentuale di lavoro del software che coinvolge questo genere di cose è pochissima. Quindi è ancora sicuro dire che queste istruzioni che hai trovato probabilmente non ti saranno più utili di una lezione di storia.

+3

+1, grazie per una lezione di storia :) –

+0

Ma se dici ai giovani che al giorno d'oggi, non ti crederanno mai ... :-) –

8

Fornire alcuni esempi pratici.

prima imparare a:

  • creare un sistema operativo bootloader minimal ed eseguirlo su QEMU e hardware reale come ho spiegato qui: https://stackoverflow.com/a/32483545/895245
  • fare qualche chiamate del BIOS per fare qualche rapido e sporco IO

Poi:

  1. PS/2 controller: ottenere l'ID scancode dell'ultimo carattere digitato sulla tastiera per al:

    in $0x60, %al 
    

    Minimal example

  2. Real Time Clock (RTC): ottenere il tempo parete con la definizione di secondi:

    .equ RTCaddress, 0x70 
    .equ RTCdata, 0x71 
    
    /* al contains seconds. */ 
    mov $0, %al 
    out %al, $RTCaddress 
    in $RTCdata, %al 
    
    /* al contains minutes. */ 
    mov $0x02, %al 
    out %al, $RTCaddress 
    in $RTCdata, %al 
    
    /* al contains hour. */ 
    mov $0x04, %al 
    out %al, $RTCaddress 
    

    Minimal example

  3. Programmable Interval Timer (PIT): gene tasso a un numero di interrupt 8 ogni 0x1234/1193181 secondi:

    mov $0b00110100, %al 
    outb %al, $0x43 
    mov $0xFF, %al 
    out %al, $0x34 
    out %al, $0x12 
    

    Minimal example

    A Linux kernel 4.2 usage. Ce ne sono altri

Testato su: QEMU 2.0.0 Ubuntu 14.04 e hardware reale Lenovo ThinkPad T400.

Come trovare i numeri di porta: Is there a specification of x86 I/O port assignment?

https://github.com/torvalds/linux/blob/v4.2/arch/x86/kernel/setup.c#L646 ha una lista di molte porte utilizzate dal kernel di Linux.

Altre architetture

Non tutte le architetture hanno tali istruzioni IO dedicati.

In ARM, ad esempio, l'I/O viene eseguito semplicemente scrivendo agli indirizzi di memoria definiti dall'hardware magico.

Penso che questo sia quello che https://stackoverflow.com/a/3221839/895245 significa "I/O mappato in memoria rispetto a I/O mappato I/O".

Dal punto di vista del programmatore, preferisco il modo ARM, dal momento che le istruzioni IO hanno già bisogno di indirizzi magici per funzionare, e abbiamo enormi spazi di indirizzi inutilizzati in indirizzamento a 64 bit.

Vedere https://stackoverflow.com/a/40063032/895245 per un esempio ARM concreto.

+1

@Downvoters, per favore spiegami ;-) –

+0

Non ho fatto downvote, ma, sebbene la risposta sia ampia, non la vedo rispondere alla domanda originale! –

+0

@CarlSmotricz grazie per il feedback. "Non lo vedo rispondere alla domanda originale!" Non ho risposto agli OPs "Che cosa sono usate le istruzioni IN & OUT in x86? 2) Non ho mai scoperto uno scenerio in cui ho bisogno di usare queste istruzioni.Quando dovrei averne bisogno? 3) Fornisci alcuni esempi pratici." abbastanza direttamente? –

1

C'è un po 'più di inganno. Non si limita a multiplexare uno spazio di indirizzamento separato di 64kb sugli stessi fili con un "extra address bus/chip select pin". Intel 8086 e 8088 e i loro cloni multiplex anche il bus dati e il bus indirizzo; tutte cose molto insolite nelle CPU. I fogli di dati sono pieni di elementi di configurazione 'minimo/massimo' e tutti i registri di latch che è necessario associare ad esso per farlo comportarsi 'normalmente'. D'altra parte, salva un carico di e gate e 'o' gates nella decodifica degli indirizzi e 64kb dovrebbe essere 'abbastanza porte i/o per tutti': P.

Inoltre, per tutte quelle persone che si occupano solo di sviluppatori di driver, prendere nota: oltre a persone che utilizzano chip compatibili con Intel in un altro hardware rispetto ai PC (non erano mai stati concepiti per l'utilizzo nel PC IBM in primo luogo - solo IBM li ha presi perché erano economici e già sul mercato), Intel vende anche microcontrollori con lo stesso set di istruzioni (Intel Quark) e ci sono un sacco di "sistemi su un chip" di altri fornitori con lo stesso set di istruzioni. Non penso che riuscirai a stipare qualcosa con "spazio utente", "kernel" e "driver" separati in 32kb :). Per la maggior parte delle cose, questi "sistemi operativi" così complessi non sono né ottimali né desiderati. Formando alcuni pacchetti UDP nella RAM e inserendoli in un buffer circolare e facendo alcuni relè, fare clic su un clic non richiede un kernel 30mb e un tempo di caricamento di 10 secondi, lo sai. È fondamentalmente la scelta migliore nel caso in cui un microcontrollore PIC non sia sufficiente ma non si desidera un intero PC industriale. Quindi le istruzioni I/O sulla porta vengono utilizzate molto e non solo dagli "sviluppatori di driver" per i sistemi operativi più grandi.

Problemi correlati