Esta pregunta es para aclarar mi duda sobre esta clase de almacenamiento de registros.
cuando una variable está calificada para el registro, el compilador coloca la variable en un registro de la CPU que no sea RAM para facilitar el acceso. entonces, ¿hay registros disponibles en una CPU para uso general (permite al usuario usarlo libremente)? (No voy a preguntar si significa algún SFR (no me gusta cambiar el significado de SFR)
En una MCU PIC (tal vez aplicable solo a la línea base), los SFR y los registros de propósito general (que es la única RAM que creo) existen juntos. ¿Aquí no puedo pensar en ninguna optimización con un 'registro' o hay?
¿Alguien podría explicar cómo logra la optimización en términos de velocidad (de acceso) en otras arquitecturas?
¿O las preguntas anteriores se deben a muchos conceptos erróneos?
Su pregunta es un poco confusa, pero tal vez esto ayude a aclararla.
Hay dos áreas a considerar:
Estos pequeños microcontroladores no tienen RAM externa. Toda la RAM es interna, pero parte de ella se usa para cosas específicas como registros.
Por ejemplo, los PIC de Microchip que menciona tienen un registro "W". Esto es solo en la RAM normal como todo lo demás, pero las instrucciones con dos operandos generalmente requieren que uno de ellos esté en el registro W.
Esto simplifica enormemente el diseño del microcontrolador a nivel electrónico y mantiene bajos los costos/energía. También tiene otros beneficios como el tiempo predecible (en ciclos) para las instrucciones.
Esta es la razón por la que verá instrucciones que cargan W con un valor, lo operan y luego lo copian de W a otra parte de la memoria. El compilador usa el registro porque tiene que hacerlo.
Otros procesadores (CPU) como x86/64 tienen RAM externa, lo que es una gran diferencia. Fíjate ahora que un "registro" significa algo muy diferente porque tenemos diferentes tipos de memoria.
Externo a la CPU hay grandes cantidades de RAM, interno a la CPU hay varios bloques de memoria más pequeños. Algunos de estos son registros de almacenamiento que contienen una cantidad de datos, generalmente igual al ancho de datos de la arquitectura. Entonces, para un procesador Intel de 32 bits, los registros (como EAX, EBX, etc.) tienen 32 bits de ancho.
Estos procesadores tienen instrucciones más complicadas que a menudo pueden operar en registros o RAM externa. Los datos para una instrucción no siempre necesitan estar en un registro. Por lo tanto, ¿por qué nos molestaríamos? La respuesta es la velocidad. Cuando haya una opción, el compilador usará registros para reducir el tiempo de ejecución.
Estos procesadores complicados tienen diferentes tiempos de acceso para diferentes tipos de memoria. Los registros que están en la matriz de la CPU son de acceso muy rápido. Entonces, si tiene una variable que está en uso constante a lo largo de algún código, tiene sentido cargarla en un registro, operarla repetidamente y luego copiarla nuevamente a la RAM externa cuando termine.
AFAIK "registrar" es solo una recomendación muy flexible para el compilador; no significa que el compilador tenga que poner la variable en un registro. La mayoría de las veces, el compilador sabe mejor dónde colocar la variable y utiliza registros siempre que sea posible. Muy a menudo la palabra clave no tiene efecto.
No conozco los detalles internos de las MCU PIC pero, en general, los procesadores tienen un número limitado de registros que pueden usar para operaciones (por ejemplo, agregar). Si una función utiliza muchas variables locales, no todas ellas pueden almacenarse en registros y al menos algunas deben ubicarse en la RAM externa. El compilador tiene una estrategia sofisticada para determinar qué variables mantener en los registros (p. ej., las que se usan con más frecuencia) y cuáles no (p. ej., las que deben estar en la memoria porque se refieren a ellas mediante punteros).
Dependería de qué compilador se use, pero tiene razón; para un procesador que no tiene nada más que registros, con el tiempo de acceso sin cambios sin importar qué registro (sin selección de banco), entonces la calificación no debería tener sentido.
Si se necesita la selección de un banco, entonces el compilador debe limitar la variable al mismo banco que está actualmente en uso en el momento de la ejecución.
Pero ¿por qué especular? Puede verificar esto comparando la salida de código ensamblador y máquina del compilador, con y sin una calificación de registro en un lugar interesante. Si no ve ninguna diferencia, sabe que la calificación no es necesaria actualmente. Sin embargo, no significa que no será útil más adelante.
(Puede usar programas de detección de diferencias, actuando sobre la salida del ensamblado. Exactamente qué programas usar depende de su preferencia. Yo usaría diff o meld en Linux, por ejemplo).
Según el procesador, el acceso a los datos en los registros se puede realizar con una instrucción más corta que el acceso a los datos en la memoria. Eso solo puede acelerar la ejecución de esa instrucción, además de ahorrar memoria del programa. La ganancia de velocidad puede ser especialmente beneficiosa dentro de un bucle. Algunas operaciones solo pueden funcionar en un registro o entre dos registros. Tener una variable en un registro en ese momento es una necesidad. Si se puede mantener en el registro, se pueden guardar dos operaciones (cargar el registro desde la memoria y almacenar el nuevo valor nuevamente en la memoria). La mayoría de los compiladores son mejores y más minuciosos que la mayoría de los programadores para descubrir la mejor manera de beneficiarse usando el número limitado de registros para ese propósito. Examine la salida del ensamblador del mismo código sinregister
especificadores, compilados con y sin optimización activada para ver qué hace y qué no asigna el optimizador a los registros.
Hoy en día, muchos compiladores tienen algoritmos de análisis de flujo de datos que pueden usar registros de manera más eficiente de lo que sería posible con un programador experto colocando cada variable en un registro o en la memoria, ya que los compiladores pueden decidir que las variables deben vivir en registros para algunas partes de su toda la vida y en la memoria de otras partes. Como tal, la función principal de la palabra clave de registro es indicar al compilador que debe prohibir cualquier intento de tomar la dirección de una variable en particular. Tomar la dirección de una variable generalmente implica que no debe mantenerse en un registro a través de las llamadas a funciones, pero para las variables cuya dirección no se toma, la palabra clave no register
necesita tener ningún efecto cuando el compilador decide cuándo mantener las variables en los registros.
Cuajada
raforanz
Cuajada
raforanz
Cuajada