El contador de programa ( PC ), [1] comúnmente llamado puntero de instrucciones ( IP ) en los microprocesadores Intel x86 e Itanium , y a veces llamado registro de dirección de instrucciones ( IAR ), [2] [1] el contador de instrucciones , [3] o simplemente parte del secuenciador de instrucciones, [4] es un registro del procesador que indica dónde se encuentra una computadora en su secuencia de programa . [5] [nb 1]
Generalmente, la PC se incrementa después de obtener una instrucción y contiene la dirección de memoria de (" apunta a") la siguiente instrucción que se ejecutará. [6] [nb 2]
Los procesadores suelen obtener instrucciones de la memoria de forma secuencial, pero las instrucciones de transferencia de control cambian la secuencia colocando un nuevo valor en la computadora. Estas incluyen bifurcaciones (a veces llamadas saltos), llamadas a subrutinas y retornos . Una transferencia que está condicionada a la verdad de alguna afirmación permite que la computadora siga una secuencia diferente en diferentes condiciones.
Una bifurcación permite que la siguiente instrucción se obtenga de otra parte de la memoria. Una llamada a una subrutina no solo se bifurca, sino que también guarda el contenido anterior de la PC en algún lugar. Un retorno recupera el contenido guardado de la PC y lo vuelve a colocar en la PC, reanudando la ejecución secuencial con la instrucción que sigue a la llamada a la subrutina.
En una unidad central de procesamiento (CPU) simple, el PC es un contador digital (que es el origen del término "contador de programa") que puede ser uno de varios registros de hardware . El ciclo de instrucción [8] comienza con una búsqueda , en la que la CPU coloca el valor del PC en el bus de direcciones para enviarlo a la memoria. La memoria responde enviando el contenido de esa ubicación de memoria en el bus de datos . (Este es el modelo de computadora de programa almacenado , en el que un solo espacio de memoria contiene tanto instrucciones ejecutables como datos ordinarios. [9] ) Después de la búsqueda, la CPU procede a la ejecución , tomando alguna acción basada en el contenido de memoria que obtuvo. En algún punto de este ciclo, el PC se modificará para que la próxima instrucción ejecutada sea una diferente (típicamente, se incrementará para que la próxima instrucción sea la que comience en la dirección de memoria inmediatamente posterior a la última ubicación de memoria de la instrucción actual).
Al igual que otros registros de procesador, el PC puede ser un banco de pestillos binarios, cada uno de los cuales representa un bit del valor del PC. [10] La cantidad de bits (el ancho del PC) se relaciona con la arquitectura del procesador. Por ejemplo, una CPU de “32 bits” puede utilizar 32 bits para poder direccionar 2 32 unidades de memoria. En algunos procesadores, el ancho del contador de programa depende en cambio de la memoria direccionable; por ejemplo, algunos microcontroladores AVR tienen un PC que se reinicia después de 12 bits. [11]
Si la PC es un contador binario, puede incrementarse cuando se aplica un pulso a su entrada COUNT UP, o la CPU puede calcular algún otro valor y cargarlo en la PC mediante un pulso a su entrada LOAD. [12]
Para identificar la instrucción actual, el PC puede combinarse con otros registros que identifican un segmento o una página . Este enfoque permite un PC con menos bits al suponer que la mayoría de las unidades de memoria de interés se encuentran en las proximidades actuales.
El uso de un PC que normalmente incrementa supone que lo que hace un ordenador es ejecutar una secuencia de instrucciones normalmente lineal. Un PC de este tipo es fundamental para la arquitectura de von Neumann . Por tanto, los programadores escriben un flujo de control secuencial incluso para algoritmos que no tienen que ser secuenciales. El “ cuello de botella de von Neumann ” resultante condujo a la investigación en computación paralela , [13] incluidos modelos no von Neumann o de flujo de datos que no utilizaban un PC; por ejemplo, en lugar de especificar pasos secuenciales, el programador de alto nivel podría especificar la función deseada y el programador de bajo nivel podría especificar esto utilizando lógica combinatoria .
Esta investigación también condujo a formas de hacer que las CPU convencionales basadas en PC funcionen más rápido, incluyendo:
Los lenguajes de programación de alto nivel modernos siguen el modelo de ejecución secuencial y, de hecho, una forma habitual de identificar errores de programación es mediante una “ejecución de procedimiento” en la que el dedo del programador identifica el punto de ejecución como lo haría un PC. El lenguaje de alto nivel es esencialmente el lenguaje de máquina de una máquina virtual, [14] demasiado complejo para ser construido como hardware, sino emulado o interpretado por software.
Sin embargo, los nuevos modelos de programación trascienden la programación de ejecución secuencial:
instrucción que se está ejecutando en ese momento. Se carga automáticamente con cero cuando se enciende o reinicia el chip. A medida que se ejecuta cada instrucción, el PC se incrementa (se incrementa en uno) para indicar la siguiente instrucción.
3.2.12. WRAPMODE […] AS asumirá que el contador de programa del procesador no tiene la longitud completa de 16 bits dada por la arquitectura, sino una longitud que es exactamente suficiente para direccionar la ROM interna. Por ejemplo, en el caso del
AT90S8515
, esto significa 12 bits, correspondientes a 4 Kwords u 8 Kbytes. Esta suposición permite saltos relativos desde el principio hasta el final de la ROM y viceversa, lo que daría como resultado un error de salto fuera de rama al utilizar aritmética estricta. En este caso, funcionan porque se descartan los bits de acarreo resultantes del cálculo de la dirección de destino. […] En el caso del AT90S8515 mencionado anteriormente, esta opción es incluso necesaria porque es la única forma de realizar un salto directo a través del espacio de direcciones completo […]