Si un 32 -bit puede manejar aproximadamente 4 GiB de RAM (es decir. \$2^{32} = 4 294 967 296\$ ) bytes, ¿por qué mi Arduino Mega 2560 tiene 8 KiB de SRAM, si siendo un 8 -le permite manejar sólo 256 bytes ( \$2^8\$ )? ¿O estoy leyendo mal la siguiente página?
Respuestas
¿Demasiados anuncios?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 no son suficientes para hacer mucho. Sólo 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, la mayoría desarrolladas cuando 64k se quedó pequeño, pero aquí estamos hablando de la idea básica).
Las líneas 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 el número máximo de bits que pueden transferirse de uno en uno (y almacenarse en la memoria), mientras que las líneas de dirección determinan el número máximo de "celdas" de memoria que pueden seleccionarse.
El hecho de que las CPU x86 de 32 bits no pudieran gestionar más de 4 GB de RAM era sobre todo una cuestión de marketing. Recuerdo en alguna parte que había pines A33-34 en las CPUs 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 bajo y una parte de orden alto. 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 direccionarlos 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" loads the accumulator with the address formed by adding $ 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:
- Finaliza la escritura del registro de la instrucción anterior (si existe) y carga el opcode ($BD)
- Obtiene el primer byte del operando que sigue al opcode ($34) mientras decodifica la instrucción
- Obtiene el segundo byte del operando ($12) mientras añade el byte obtenido previamente al registro X
- Leer la memoria en la dirección formada por la concatenación del byte del segundo operando con el resultado de la ALU [es decir, $1224]. Introducir el segundo byte operando en la ALU para sumar cero o uno dependiendo de si la suma anterior generó un acarreo.
- Leer memoria en la dirección formada al reemplazar la mitad superior con el resultado de la ALU [$1334]
La transferencia del byte leído al acumulador se solapará con la obtención de la siguiente instrucción. Además, para muchas operaciones, si el paso 3 no generara un acarreo, el paso 4 habría leído la dirección correcta y la ejecución podría saltar directamente del paso 4 a la siguiente instrucción, omitiendo el paso 5.
Si se examina la secuencia de operaciones, se observará 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 tarde un ciclo en realizar una suma, es posible leer un byte de la dirección calculada sin esperar al resultado de la ALU, ya que normalmente el byte alto que se ha obtenido será el byte alto del operando de destino. En una máquina big-endian con una ALU de 8 bits, una carga indexada tardarí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).
Suele ser cierto que existe cierta 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 motivos. 256 bytes de espacio de direcciones se consideraba demasiado pequeño 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 se dirigían a 64 kilobytes. Sin embargo, con la conmutación de bancos (esencialmente utilizando 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 patillas en el dispositivo para llegar a todo el espacio que podían direccionar sus registros internos de direcciones. Por ejemplo, en el Motorola 68000, sólo 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.
Responderé a esta pregunta específicamente para los controladores AVR que has mencionado. 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 es capaz de utilizar 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 ello. Juntos forman el puntero Z.
En ensamblador 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 utilizar para esto. Están diseñados específicamente en hardware para permitir este tipo de operaciones.
Cuando se programa en un lenguaje de alto nivel como C, el compilador se encarga de estas cosas.
Nota: Algunos AVRs soportan incluso tamaños de memoria superiores a 64k. Estos controladores disponen de 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 (normalmente sólo se utiliza 1 bit), ZH (8bit), ZL (8bit). Esto da como resultado una dirección total de 17 bits y permite acceder a 128 kiB de RAM.
- Ver respuestas anteriores
- Ver más respuestas