assembly - lea - x86 instruction reference
¿Para qué se utilizan las instrucciones IN & OUT en x86? (7)
¿Sabes cómo funciona el direccionamiento de memoria? Hay un bus de direcciones, un bus de datos y algunas líneas de control. La CPU pone la dirección de un byte (o un byte inicial) en la memoria del bus de direcciones, luego eleva la señal de lectura, y algunos chips RAM devuelven el contenido de la memoria en esa dirección subiendo o bajando líneas individuales (correspondientes a bits) en el (los) octeto (s)) en el bus de datos. Esto funciona tanto para RAM como para ROM.
Pero también hay dispositivos de E / S: puertos serie y paralelo, el controlador para el pequeño altavoz interno de una PC, controladores de disco, chips de sonido, etc. Y esos dispositivos también se leen y escriben en. También deben abordarse para que la CPU acceda al dispositivo correcto y (normalmente) a la ubicación de datos correcta dentro de un dispositivo determinado.
Para algunos modelos de CPU, incluida la serie xxx86, que se encuentran en la mayoría de las PC "modernas", los dispositivos de E / S comparten el espacio de direcciones con la memoria. Ambos dispositivos RAM / ROM e IO están conectados a la misma dirección, datos y líneas de control. Por ejemplo, el puerto serie para COM1 se dirige a partir de (hex) 03F8. Pero casi seguro hay memoria en la misma dirección.
Aquí hay un diagrama realmente simple:
[ ]
Claramente, la CPU necesita hablar con la memoria o el dispositivo de E / S, nunca con ambos. Para distinguir entre los dos, una de las líneas de control llamada "M / # IO" afirma si la CPU desea hablar con la memoria (línea = alta) o con un dispositivo de E / S (línea = baja).
La instrucción IN se lee desde un dispositivo de E / S, escribe OUT. Cuando utiliza las instrucciones IN o OUT, el M / # IO no se afirma (se mantiene bajo), por lo que la memoria no responde y el chip de E / S sí lo hace. Para las instrucciones orientadas a la memoria, M / # IO se afirma para que la CPU se comunique con la RAM, y los dispositivos IO permanecen fuera de la comunicación.
Bajo ciertas condiciones, los dispositivos IO pueden conducir las líneas de datos y la RAM puede leerlas al mismo tiempo. Y viceversa. Se llama DMA.
Tradicionalmente, los puertos de serie e impresora, así como el teclado, el mouse, los sensores de temperatura, etc., eran dispositivos de E / S. Los discos estaban en el medio; las transferencias de datos serían iniciadas por los comandos de E / S, pero el controlador de disco usualmente depositaría directamente sus datos en la memoria del sistema.
En los sistemas operativos modernos, como Windows o Linux, el acceso a los puertos de E / S está oculto a los programas de usuario "normales", y hay capas de software, instrucciones privilegiadas y controladores para manejar el hardware. Entonces, en este siglo, la mayoría de los programadores no se ocupan de esas instrucciones.
Los he encontrado en las instrucciones IN & OUT mientras leo el libro "Understanding Linux Kernel". He buscado el manual de referencia.
5.1.9 Instrucciones de E / S
Estas instrucciones mueven datos entre los puertos de E / S del procesador y 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
No obtuve algunas cosas:
- "puertos de E / S del procesador". ¿Qué son? ¿Por qué querríamos leer y escribir "cadenas" desde y hacia estos puertos?
- Nunca encontré un escenario en el que necesite usar estas instrucciones. ¿Cuándo necesitaría esto?
- Da algunos ejemplos prácticos.
CPU conectada a algunos controladores externos a través de io puertos. en una PC x86 vieja, trabajo con una unidad de disquete usando puertos de E / S. si sabe qué comandos aceptan el controlador del dispositivo, puede programarlo a través de sus puertos.
En el mundo moderno, nunca usarás instrucciones de puertos. Excepción si usted es (o será) desarrollador del controlador.
hay información más detallada acerca de los puertos de E / S http://webster.cs.ucr.edu/AoA/DOS/ch03/CH03-6.html#HEADING6-1
Comience con algo como esto:
http://www.cpu-world.com/info/Pinouts/8088.html
Está aprendiendo las instrucciones para un chip / arquitectura de tecnología muy antigua. Cuando todo menos el núcleo del procesador estaba fuera de chip. ¿Ves las líneas de dirección y las líneas de datos y hay una línea de lectura RD y una línea de escritura WR y una línea IO / M?
Había dos tipos de instrucciones basadas en memoria y basadas en E / S porque había espacios direccionables, fácilmente decodificados por IO / M IO o Memoria.
Recuerde que tenía 74LSxx pegamento lógico, muchos cables y muchas virutas para conectar una memoria al procesador. Y la memoria era solo ese recuerdo, grandes chips caros. Si tenía un periférico que necesitaba hacer algo útil, también tenía registros de control, la memoria podría ser datos de píxeles, pero en algún lugar que necesitara establecer los límites de relojes de exploración horizontal y vertical, estos podrían ser cierres 74LSxx individuales, NO memorias, teniendo I / O E / S asignadas guardadas en la lógica de pegamento y que tenían mucho sentido desde la perspectiva del programador, también evitaba cambiar los registros de segmento para apuntar tu ventana de memoria de 64 K, etc. El espacio de dirección de memoria era un recurso sagrado, especialmente cuando Quería limitar la decodificación de su dirección a unos pocos bits porque cada pocos bits le costará una cantidad de chips y cables.
Al igual que la E / S mapeada de memoria grande y pequeña endian, la E / S mapeada de E / S era una guerra religiosa. Y algunas de las respuestas que verá en su pregunta reflejarán las fuertes opiniones que aún existen hoy en día en las personas que la vivieron. La realidad es que cada chip en el mercado de hoy tiene múltiples negocios para varias cosas, no cuelga su reloj de tiempo real del bus de memoria ddr con un descodificador de direcciones. Algunos incluso tienen buses de instrucción y datos completamente separados. En cierto sentido, Intel ganó la guerra por el concepto de espacios de direcciones separados para diferentes clases de cosas a pesar de que el término puerto de E / S es malo y malo, y no debería pronunciarse durante, digamos, 20-30 años más. Necesitas personas de mi edad que vivieron para jubilarse o desaparecer antes de que la guerra haya terminado realmente. Incluso el término memoria asignada E / S es una cosa del pasado.
Eso es realmente todo lo que alguna vez fue, un bit de decodificación de dirección única en el exterior del chip de Intel que fue controlado por el uso de instrucciones específicas. Utiliza un conjunto de instrucciones sobre el bit en uso, un conjunto de instrucciones, el bit estaba desactivado. Si desea ver algo interesante, consulte el conjunto de instrucciones para los procesadores xmos xcore, tienen muchas cosas que son instrucciones en lugar de registros mapeados en memoria, lleva esta E / S mapeada de E / S a un nivel completamente nuevo.
Donde se usó es como describí anteriormente, pondría cosas que tenían sentido y podría permitirse grabar espacio de direcciones de memoria para píxeles de video similares, memoria de paquetes de red (tal vez), memoria de tarjeta de sonido (bueno tampoco eso, pero podría tener ), etc. Y los registros de control, el espacio de direcciones relativo a los datos era muy pequeño, tal vez solo unos pocos registros, se decodificaron y se usaron en el espacio de E / S. los más obvios son / eran puertos serie y puertos paralelos que tenían poco o ningún almacenamiento, es posible que haya tenido un pequeño fifo en el puerto serie, en todo caso.
Debido a que el espacio de direcciones era escaso, no era infrecuente y todavía se ve hoy en día tener memoria oculta detrás de dos registros, un registro de direcciones y un registro de datos, esta memoria solo está disponible a través de estos dos registros, no se mapeó la memoria. por lo que escribe el desplazamiento en esta memoria oculta en el registro de direcciones y lee o escribe el registro de datos para acceder al contenido de la memoria. Ahora, porque Intel tenía la instrucción de repetición y podía combinarla con insb / w outsb / w, el decodificador de hardware (si tenía gente amable / amigable trabajando con usted) autoincrementa la dirección cada vez que hacía un ciclo de E / S. Por lo tanto, podría escribir la dirección de inicio en el registro de direcciones y hacer una repetición y sin grabar los ciclos de reloj de recuperación y decodificación en el procesador y en el bus de memoria podría mover los datos bastante rápido dentro o fuera del periférico. Este tipo de cosas ahora se considera un defecto de diseño gracias a los procesadores súper escalares modernos con recuperaciones basadas en la predicción de bifurcaciones, su hardware puede experimentar lecturas en cualquier momento que no tienen nada que ver con la ejecución del código, como resultado NUNCA debe aumentar automáticamente direccionar o borrar bits en un registro de estado o modificar cualquier cosa como resultado de una lectura a una dirección.
Los mecanismos de protección integrados en el 386 y en el presente en realidad hacen que sea muy fácil acceder a E / S desde el espacio del usuario. Dependiendo de lo que haga para ganarse la vida, lo que produce su empresa, etc. Definitivamente puede utilizar la familia de instrucciones de entrada y salida del espacio de usuario (programas de aplicación en Windows y Linux, etc.) o espacio kernel / controlador, es su elección. También puede hacer cosas divertidas como aprovechar la máquina virtual y usar las instrucciones de E / S para hablar con los conductores, pero eso probablemente molestaría a la gente en los mundos de Windows y Linux, ese controlador / aplicación no llegaría muy lejos. Los otros carteles son correctos, ya que es probable que nunca necesite usar estas instrucciones a menos que esté escribiendo controladores, y es probable que nunca escriba controladores para dispositivos que usan E / S asignadas de E / S porque sabe ... el controladores para esos dispositivos heredados ya han sido escritos. Los diseños modernos definitivamente tienen E / S pero está mapeada en la memoria (desde la perspectiva de los programadores) y usa instrucciones de memoria y no de E / S. Ahora el otro lado si esto es DOS definitivamente no está muerto, dependiendo de dónde usted puede estar construyendo máquinas de votación o bombas de gasolina o cajas registradoras o una larga lista de equipos basados en DOS. De hecho, si trabaja en algún lugar que construye PC o periféricos basados en PC o placas base, las herramientas basadas en DOS todavía se usan ampliamente para probar y distribuir actualizaciones de BIOS y otras cosas similares. Todavía me encuentro con situaciones en las que tengo que tomar el código de un programa actual de prueba de dos para escribir un controlador de Linux. Al igual que no todos los que pueden lanzar o atrapar un balón de fútbol juegan en la NFL, en porcentaje, muy pocos hacen un trabajo de software que involucre este tipo de cosas. Por lo tanto, es seguro decir que estas instrucciones probablemente no sean más para usted que una lección de historia.
En el nivel de hardware, la mayoría de los microprocesadores tienen poca o ninguna capacidad de E / S integrada. Algunos procesadores tienen uno o más pines que se pueden encender y apagar usando instrucciones especiales, y / o uno o más pines que pueden probarse usando instrucciones de rama, pero tales características son raras. En cambio, las E / S generalmente se manejan conectando el sistema de modo que los accesos a un rango de direcciones de memoria activarán algún efecto, o incluyendo instrucciones de "entrada" y "salida" que se comportan como operaciones de carga / almacenamiento de memoria excepto que una señal especial se emite diciendo "Esto es una operación de E / S en lugar de una operación de memoria". En la época de los procesadores de 16 bits, solía haber algunas ventajas reales al tener instrucciones especializadas de entrada / salida. Hoy en día, tales ventajas son en gran medida discutibles, ya que uno podría simplemente asignar una gran parte del espacio de direcciones de uno a E / S y aún le quedará mucho para memoria.
Dado que un programa podría causar estragos considerables en un sistema al realizar incorrectamente las instrucciones de E / S (por ejemplo, tales instrucciones podrían realizar accesos de disco arbitrarios), todos los sistemas operativos modernos prohíben el uso de tales instrucciones en el código de nivel de usuario. Algunos sistemas pueden permitir que tales instrucciones sean virtualizadas; si el código de usuario intenta escribir en los puertos de E / S 0x3D4 y 0x3D5, por ejemplo, un sistema operativo podría interpretar eso como un intento de establecer algunos registros de control de control de video para mover el cursor parpadeante. Cada vez que el programa de usuario realizaba la instrucción OUT, el sistema operativo tomaría el control, vería lo que el programa de usuario intentaba hacer y actuaría de manera apropiada.
En la gran mayoría de los casos, incluso si el sistema operativo traduce una instrucción IN o OUT en algo adecuado, sería más eficiente solicitar directamente al sistema operativo la acción adecuada.
Hay un truco un poco más que eso. No solo multiplexa un espacio de direcciones separado de 64 kb en los mismos cables con un ''pin de selección de bus de dirección / chip adicional''. Intel 8086 y 8088 y sus clones también multiplexan el bus de datos y el bus de direcciones; todas las cosas poco comunes en las CPU. Las hojas de datos están llenas de elementos de configuración ''mínimo / máximo'' y todos los registros de enganche que necesita conectar para hacer que se comporte ''normalmente''. Por otro lado, ahorra una carga de compuertas y compuertas ''o'' en decodificación de direcciones y 64kb deberían ser ''suficientes puertos de E / S para todos'': P.
Además, para todas esas personas que solo tienen "controladores únicos", tomen nota: además de las personas que usan chips compatibles con Intel en otro hardware además de las PC (en realidad nunca fueron diseñados para ser utilizados en IBM PC) IBM simplemente los tomó porque eran baratos y ya están en el mercado), Intel también vende microcontroladores con el mismo conjunto de instrucciones (Intel Quark) y hay muchos "sistemas en un chip" de otros proveedores con el mismo conjunto de instrucciones. No creo que puedas meter nada con un "espacio de usuario" kernel y drivers en 32kb :). Para la mayoría de las cosas, estos "sistemas operativos" complejos no son ni óptimos ni deseados. Formar algunos paquetes UDP en la RAM y luego ponerlos en algún buffer de anillo y hacer que algunos relés hagan click clic no requiere un kernel de 30mb y un tiempo de carga de 10 segundos, ya sabes. Básicamente es la mejor opción en caso de que un microcontrolador PIC no sea suficiente, pero no quieres una PC industrial completa. Por lo tanto, las instrucciones de E / S del puerto se usan mucho y no solo por los "desarrolladores de controladores" para sistemas operativos más grandes.
Si no está escribiendo un sistema operativo, nunca usará estas instrucciones.
Las máquinas basadas en x86 tienen dos espacios de direcciones independientes: el espacio de direcciones de memoria con el que está familiarizado, y luego el espacio de direcciones de E / S. Las direcciones del puerto de E / S solo tienen 16 bits de ancho, y los registros de bajo nivel de referencia y otros widgets de bajo nivel que forman parte de un dispositivo de E / S: algo así como un puerto en serie o paralelo, un controlador de disco, etc.
No hay ejemplos prácticos porque solo los utilizan los controladores de dispositivo y los sistemas operativos.
Da algunos ejemplos prácticos.
Primero aprende cómo:
- cree un sistema operativo de gestor de arranque mínimo y ejecútelo en QEMU y en el hardware real como he explicado aquí: https://.com/a/32483545/895245
- hacer algunas llamadas al BIOS para hacer un IO rápido y sucio
Entonces:
Controlador PS / 2 : obtenga la ID del scancode del último carácter escrito en el teclado para
al
:in $0x60, %al
Reloj de tiempo real (RTC) : obtenga el tiempo de pared con la definición de segundos:
.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
Temporizador de intervalo programable (PIT) : genere un número de interrupción 8 cada
0x1234 / 1193181
segundos:mov $0b00110100, %al outb %al, $0x43 mov $0xFF, %al out %al, $0x34 out %al, $0x12
Un uso de Linux kernel 4.2 . Hay otros.
Probado en: QEMU 2.0.0 Ubuntu 14.04, y hardware real Lenovo ThinkPad T400.
Cómo encontrar los números de puerto: ¿hay una especificación de asignación de puerto de E / S x86?
https://github.com/torvalds/linux/blob/v4.2/arch/x86/kernel/setup.c#L646 tiene una lista de muchos puertos utilizados por el kernel de Linux.
Otras arquitecturas
No todas las arquitecturas tienen tales instrucciones dedicadas de IO.
En ARM, por ejemplo, IO se realiza simplemente escribiendo a las direcciones de memoria definidas por el hardware mágico.
Creo que esto es lo que https://.com/a/3221839/895245 significa mediante "E / S asignadas en memoria frente a E / S asignadas de E / S".
Desde el punto de vista del programador, prefiero el modo ARM, ya que las instrucciones IO ya necesitan direcciones mágicas para operar, y tenemos espacios de direcciones inusitados en el direccionamiento de 64 bits.
Consulte https://.com/a/40063032/895245 para obtener un ejemplo concreto de ARM.