Si un procesador de 32 bits puede manejar aproximadamente 4 GiB de RAM (es decir, ) bytes, ¿por qué mi Arduino Mega 2560 tiene 8 KiB de SRAM, si al ser un procesador de 8 bits le permite manejar solo 256 bytes ( )? ¿O estoy leyendo mal la siguiente página?
La mayoría de las CPU de 8 bits tienen buses de direcciones de 16 bits que les permiten direccionar 64kbytes, ¡precisamente porque 256 bytes realmente no son suficientes para hacer mucho! Simplemente significa que necesitan cargar dos bytes en lugar de uno, cada vez que necesitan cargar una dirección. Un poco más lento pero tolerable teniendo en cuenta su tamaño.
(Y sí, hay muchas excepciones, en su mayoría desarrolladas cuando 64k se volvió demasiado pequeño, pero aquí estamos hablando de la idea básica).
El bus de direcciones y el bus de datos están separados, por lo que pueden tener diferentes tamaños. Para cualquier tamaño de bus de dirección específico, hay muchas técnicas para direccionar más memoria que el ancho de bit de registro
La forma más común es aumentar el ancho del bus de direcciones de alguna manera
usando múltiples registros para la dirección
X
de direccionamiento de datos para permitir un máximo de 64 KB de RAM. Estos, a su vez, se pueden emparejar con , , para acceder a direcciones de RAM más altas en versiones aún más grandes. También tiene para los bytes altos del puntero de pila además de en variantes con más de 256 bytes de RAM 1Y
Z
RAMPX
RAMPY
RAMPZ
SPH
SPL
H
& L
, B
& C
, D
& E
que se pueden usar juntos como un registro de direcciones de 16 bitsusando un solo registro especial grande más grande que el tamaño natural para direccionar
utilizando un registro especial para la parte alta de la dirección . Al direccionar alguna memoria, por defecto, los 8 bits bajos de la dirección se tomarán del registro inmediato de 8 bits o de 8 bits en un microcontrolador de 8 bits, mientras que los bits altos se reemplazarán por el valor del otro registro de dirección.
call
o goto
, 8 o 9 bits bajos de la dirección se indican mediante el valor inmediato y el resto se toma del contador del programa actual. Por lo tanto, acceder a cualquier cosa que no esté muy lejos del segmento actual usa solo 1 instrucción, mientras que otras direcciones necesitarán 2 instrucciones (para configurar los bits altos).PC
mientras salta incondicionalmente.Otra forma de lograr esto es la banca de memoria . Este es un método útil que todavía se usa en algunas arquitecturas hoy en día. En este modelo, la memoria se divide en varios bancos . Cada vez que sólo puede dirigirse a un banco específico. A menudo, hay un banco global o un rango de direcciones que siempre están visibles en cualquier momento, pero para otras partes, debe cambiar de banco cuando sea necesario.
También hay una técnica no muy común pero que se puede encontrar en el Intel 8051 . Como microcontrolador con dirección de datos de 8 bits, puede tener como máximo 256 direcciones. La mitad del espacio (la parte alta) se utiliza para registros de funciones especiales ( SFR ), lo que limita la RAM real direccionable a solo 128 bytes. Sin embargo, los fabricantes modernos de la serie 8051 encontraron una forma inteligente de superar esto separando el acceso a la memoria . El direccionamiento directo accederá al SFR mientras que el direccionamiento indirecto a través de los registros accederá a la parte alta de la RAM, lo que significa que ahora tiene 256 + 128 = 384 bytes direccionables.
1 https://en.wikipedia.org/wiki/Atmel_AVR_instruction_set#Memory_addressing_instructions
Los núcleos más pequeños tienen ≤256 bytes de espacio de direcciones de datos (lo que significa ≤128 bytes de RAM después de eliminar los puertos de E/S y otras direcciones reservadas) y ≤8192 bytes (8 KiB) de ROM de programa. Estos tienen solo un puntero de pila de 8 bits (en SPL) y solo admiten las instrucciones de llamada/salto relativo de 12 bits RJMP/RCALL. (Debido a que el contador del programa AVR cuenta palabras de 16 bits, no bytes, un desplazamiento de 12 bits es suficiente para direccionar 213 bytes de ROM).
Las capacidades adicionales de direccionamiento de memoria están presentes según sea necesario para acceder a los recursos disponibles:
- Los modelos con >256 bytes de espacio de direcciones de datos (≥256 bytes de RAM) tienen un puntero de pila de 16 bits, con la mitad superior en el registro SPH.
- Los modelos con >8 KiB de ROM agregan las instrucciones JUMP y CALL de 2 palabras (22 bits). (Algunos de los primeros modelos sufren una errata si una instrucción de salto es seguida por una instrucción de 2 palabras).
- Los modelos con >64 KiB de ROM agregan la instrucción ELPM y el registro RAMPZ correspondiente. Instrucciones LPM cero-extienden la dirección ROM en Z; Las instrucciones ELPM anteponen el registro RAMPZ para bits altos. Esto no es lo mismo que la instrucción LPM más general; existen modelos "clásicos" con solo la forma de cero operandos de ELPM (ATmega103 y at43usb320). Cuando el incremento automático está disponible (la mayoría de los modelos), actualiza la dirección completa de 24 bits, incluida RAMPZ.
- Los modelos (poco comunes) con >128 KiB de ROM tienen un contador de programa de 3 bytes. Las llamadas y devoluciones de subrutinas usan un byte adicional de espacio de pila, hay un nuevo registro EIND para proporcionar bits altos adicionales para llamadas y saltos indirectos, y hay nuevas instrucciones extendidas EIJMP y EICALL que usan EIND:Z como la dirección de destino. (Las instrucciones IJMP e ICALL anteriores utilizan Z con extensión cero).
- Los modelos (poco comunes) con >64 KiB de espacio de direcciones de RAM amplían los límites de direccionamiento de RAM de 16 bits con registros RAMPX, RAMPY, RAMPZ y RAMPD. Estos proporcionan bits altos adicionales para los modos de direccionamiento que utilizan los pares de registros X, Y o Z, respectivamente, o las instrucciones de direccionamiento directo LDS/STS. A diferencia del acceso a la ROM, no hay instrucciones "extendidas" distintas; en su lugar, los registros RAMP se utilizan incondicionalmente.
Las líneas de bus de datos (pines) y las líneas de dirección (pines) están completamente separadas. En pocas palabras, las líneas de bus de datos determinan la cantidad máxima de bits que se pueden transferir de uno en uno (y almacenar en la memoria), mientras que las líneas de dirección determinan la cantidad máxima de "celdas" de memoria que se pueden seleccionar.
Fue principalmente una cuestión de marketing que las CPU x86 de 32 bits no podían manejar más de 4 GB de RAM. Recuerdo en alguna parte que había pines A33-34 en las CPU Pentium 4.
Casi todos los procesadores de 8 bits tienen alguna capacidad para formar una dirección de 16 bits a partir de una parte de orden inferior y una parte de orden superior. En algunos procesadores, incluido el 8080 original, hay registros dedicados a contener la parte superior e inferior de una dirección (aunque desde el punto de vista del programador puede haber algunos registros como el puntero de pila del 8080 que no ofrecen instrucciones para abordarlos por separado). En algunos otros procesadores, no hay registros dedicados a la mitad superior o inferior de una dirección, sino que las direcciones se ensamblan "sobre la marcha". Por ejemplo, en el 6502, la instrucción "LDA $1234,X" carga el acumulador con la dirección formada al sumar $1234 al registro X de 8 bits [supongamos que contiene $F0]. La ejecución de esa instrucción procedería en 4 o 5 pasos:
La transferencia del byte leído al acumulador se superpondrá a la obtención de la siguiente instrucción. Además, para muchas operaciones, si el paso 3 no generó un acarreo, el paso 4 habría leído la dirección correcta y la ejecución podría pasar directamente del paso 4 a la siguiente instrucción, pasando por alto el paso 5.
Si uno examina la secuencia de operaciones, notará que una arquitectura little-endian tiene una clara ventaja sobre una big-endian, ya que en la mayoría de los casos (aunque no en el que se muestra), aunque la ALU toma un ciclo para realizar Además, es posible leer un byte de la dirección calculada sin esperar el resultado de ALU, ya que normalmente el byte alto que se obtuvo será el byte alto del operando de destino. En una máquina big-endian con una ALU de 8 bits, una carga indexada tomaría al menos 5 ciclos (ya que la mitad inferior de la dirección no se leería hasta el paso 3 y, por lo tanto, se calcularía en el paso 4).
Responderé esta pregunta específicamente para los controladores AVR que mencionaste. El principio básico también es válido para muchas otras arquitecturas de 8 bits.
Los AVR son núcleos de 8 bits. Esto significa que tienen registros de 8 bits. Sin embargo, 8 bits no son suficientes para acceder a una cantidad utilizable de memoria. Por lo tanto, el núcleo AVR puede usar un conjunto específico de registros combinados como registros de puntero de 16 bits. Los registros r30 y r31 (también conocidos como ZL y ZH) son un ejemplo de esto. Juntos forman el puntero Z.
En el ensamblaje, la lectura de un byte en la dirección 0x1234 se vería así:
ldi ZL, 0x34 ; Load r30 (ZL) with low byte of address
ldi ZH, 0x12 ; Load r31 (ZH) with high byte of address
ld r16, Z ; Load byte to r16
La familia AVR tiene 3 pares de registros que se pueden usar para esto. Están específicamente diseñados en hardware para permitir este tipo de operaciones.
Cuando se programa en un lenguaje de nivel superior como C, el compilador maneja estas cosas.
Nota: algunos AVR incluso admiten tamaños de memoria superiores a 64k. Estos controladores tienen un registro de función especial en el que se escriben bits adicionales de la dirección antes del acceso. Por lo tanto, la dirección consta de los siguientes bits (MSB a LSB):
Registro de función especial (generalmente solo se usa 1 bit), ZH (8 bits), ZL (8 bits). Esto da como resultado una dirección total de 17 bits y permite acceder a 128 kiB de RAM.
A menudo es cierto que existe alguna relación entre el tamaño de la memoria direccionable y el tamaño del registro interno, aunque la relación varía por diferentes razones. 256 bytes de espacio de direcciones se consideraban demasiado pequeños incluso en los primeros días de los microprocesadores, por lo que la mayoría de los procesadores de ocho bits producían direcciones de 16 bits (dos bytes), que direccionaban 64 kilobytes. Sin embargo, con el cambio de banco (esencialmente usando ciertas líneas de E/S para producir aún más líneas de dirección), era posible tener mucho más.
En los primeros procesadores de 16 y 32 bits, no siempre había suficientes pines en el dispositivo para alcanzar todo el espacio que podían abordar sus registros de direcciones internas. Por ejemplo, en el Motorola 68000, solo había suficientes pines de dirección (24) para direccionar 16 megabytes de RAM, aunque los registros de dirección internos tenían 32 bits de ancho.
Wikipedia lo explica bastante bien:
Las CPU de ocho bits usan un bus de datos de 8 bits y, por lo tanto, pueden acceder a 8 bits de datos en una sola instrucción de máquina. El bus de direcciones suele tener un ancho de doble octeto (es decir, 16 bits), debido a consideraciones prácticas y económicas. Esto implica un espacio de direcciones directo de solo 64 KB en la mayoría de los procesadores de 8 bits.
Los AVR de 8 bits de Atmel en realidad usan una dirección de datos de 16 bits. Tienen muchos otros registros de 16 bits e incluso algunos temporizadores de 16 bits. Dado que es solo un procesador de 8 bits, generalmente usa dos ciclos de reloj para cargar un registro de 16 bits.
La noción de que el "ancho de bit" de un procesador establece la cantidad máxima de RAM que el procesador puede manejar es uno de los mitos más generalizados en la informática. De hecho, la historia de la industria está plagada de CPU para las que esta relación no se mantuvo.
HP 21MX, HP 1000: CPU de 16 bits, memoria hasta 16 MB
PDP-11: CPU de 16 bits, memoria de 4 MB
VAX-11/780: CPU de 32 bits, memoria de 512 MB
etcétera etcétera.
Juan U.
la abeja ocupada
eliot alderson
Lundin
viejo contador de tiempo