¿Cómo puede un procesador de 8 bits admitir más de 256 bytes de RAM?

Si un procesador de 32 bits 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 al ser un procesador de 8 bits le permite manejar solo 256 bytes ( 2 8 )? ¿O estoy leyendo mal la siguiente página?

http://www.atmel.com/devices/atmega2560.aspx?tab=parameters

Seguramente cualquier máquina completa de Turing es capaz de manejar casi cualquier tamaño de carnero, con el tiempo suficiente.
En realidad, la cantidad de bits en el nombre de un procesador solo se puede usar para una estimación inicial del ancho de datos interno. El 8088 es un procesador de 16 bits debido a sus registros de 16 bits, pero tiene un bus de datos de 8 bits y un bus de direcciones de 20 bits. El 68000 es un procesador de 32 bits llamado principalmente 16/32 bits debido a sus registros de 32 bits, pero tiene un bus de datos de 16 bits y un bus de direcciones de 24 bits. Las implementaciones pequeñas de ARM son procesadores de 32 bits (registros de 32 bits y bus de datos), pero incluso si usan 32 bits para las direcciones, no pueden direccionar un total de 4 GB.
He agregado los prefijos SI correctos para estas unidades. 2 30 es gibi (Gi) y 2 10 es kibi (ki).
Vale la pena mencionar que muchos 8 bits (particularmente los derivados de Motorola) admiten la llamada página cero , que era soporte de conjunto de instrucciones para manejar los primeros 256 bytes direccionables en el mapa de memoria un poco más rápido. Por lo tanto, los registros de hardware más críticos en el tiempo, etc., se asignarían a los primeros 256 bytes por este motivo de rendimiento. Esta es la razón por la que encontrará registros de hardware asignados desde la dirección cero en muchas arquitecturas.
llamar a algo de 8 bits, 16 bits, 32 bits, etc. es, digamos, un término de marketing, los ingenieros lo usan para entender que eso no significa que todo en ese procesador sea tan amplio. algunas personas usan el tamaño de la instrucción, muy a menudo se usa el tamaño de los registros de propósito general, a veces el bus. tiene el contador del programa que no siempre está accesible o utilizable en las instrucciones para que pueda ser tan amplio como desee. luego, como con muchos de los procesadores de tipo AVR, hay un esquema de registro múltiple o paginación o ambos para obtener una dirección de carga/almacenamiento más amplia para las transacciones de datos.

Respuestas (9)

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).

De hecho, la mayoría de los microcontroladores de 8 bits que he encontrado no tienen direcciones de 16 bits.
@Brian Drummond ¿Estoy en lo correcto? El controlador escribirá primero los 8 bits inferiores, luego los 8 bits superiores y luego bloqueará el bus de direcciones. ¡Así es como accederá al bus de direcciones de 16 bits!
O 8 bits superiores y luego 8 bits inferiores, pero básicamente sí, esa es la idea.
Algunos microcontroladores como el PIC18 tienen un registro de segmento que les permite expandir su espacio de direcciones más allá de lo que se puede codificar en el conjunto de instrucciones de 16 bits. Además, el uso de pines IO como selecciones de chips en bancos de RAM externos se puede usar para expandir la memoria.

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

      • AVR tiene R26..R31 que se puede emparejar en 16 bits y registros Xde 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 1YZRAMPXRAMPYRAMPZSPHSPL
      • Intel 8080 y Zilog Z80 son CPU de 8 bits, pero tienen pares de registros como H& L, B& C, D& Eque se pueden usar juntos como un registro de direcciones de 16 bits
    • usando un solo registro especial grande más grande que el tamaño natural para direccionar

      • Intel 8051 es un microcontrolador de 8 bits, es decir, tiene una dirección de datos de 8 bits. Sin embargo, utiliza direcciones de instrucciones de 16 bits y tiene 2 registros de 16 bits: PC y DPTR para direccionamiento en el espacio de instrucciones.
      • AVR tiene un registro de PC de 16 o 22 bits
    • 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.

      • Un caso especial de esto es la memoria segmentada , que es utilizada por el x86 de 16 bits . En esta técnica, la memoria se divide en varios segmentos de tamaño 64 KB (2 16 bytes). El acceso normal está dentro de un solo segmento de forma predeterminada, por lo que pueden usar una dirección de 16 bits para datos cercanos . Los datos que están más separados deben direccionarse específicamente por valor de segmento, por lo tanto, se deben usar 2 registros para el direccionamiento lejano.
      • El microcontrolador PIC , cuya serie básica y de rango medio puede tener direcciones de 13 o 14 bits, es otro ejemplo. Cuando se usa la instrucción callo 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).
      • Otro ejemplo es la arquitectura MIPS que también combina la dirección inmediata inferior de 26 bits con los 6 bits superiores PCmientras 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.

    • Intel 8051 utiliza bancos de memoria para los registros. Tiene 32 registros pero solo 8 de ellos son visibles a la vez.
    • x86 PAE y ARM LPAE , con mayor espacio de direcciones físicas asignado a un pequeño espacio de direcciones virtuales
    • Otra aplicación para esto es Address Windowing Extensions en Windows, que pueden usar las aplicaciones x86 de 32 bits en modo PAE para acceder a más de 2/3 GB de memoria. No es exactamente como un banco de memoria en los microcontroladores, pero puede verse como tal, porque el gran rango de direcciones se puede pensar en pequeñas ventanas/bancos que son lo suficientemente pequeños como para caber en el espacio de direcciones de la aplicación. Si la aplicación necesita usar datos en alguna ventana, asignará esa ventana a su espacio de direcciones actual.
    • DOS también tiene algunos tipos de cambio de banco como memoria expandida o memoria extendida debido a su rango limitado de memoria direccionable.
  • 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:

  1. 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.
  2. 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).
  3. 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.
  4. 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).
  5. 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.

Tiene razón: PAE permitió el uso de más RAM, pero como no estaba disponible en el escritorio de Windows, no mucha gente lo usó.
PAE es el nombre de la característica. Además, los procesadores de 64 bits no pueden manejar 64 exabytes, como 2 64 podría sugerir.
Las CPU x86 no pueden manejar más de 4 GB sin complicaciones significativas en el sistema operativo que no se adaptan a otras arquitecturas.
@Kaz ARM de 32 bits tiene una función similar llamada LPAE, que permite que el sistema operativo aborde más de 32 bits de dirección

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:

  1. Finalice el registro de escritura de la instrucción anterior (si corresponde) y cargue el código de operación ($BD)
  2. Obtenga el primer byte del operando después del código de operación ($34) mientras decodifica la instrucción
  3. Obtenga el segundo byte del operando ($ 12) mientras agrega el byte obtenido previamente al registro X
  4. Lea la memoria en la dirección formada al concatenar el segundo byte del operando con el resultado de ALU [es decir, $1224]. Introduzca el segundo byte de operando en ALU para agregar cero o uno dependiendo de si el agregado anterior generó un acarreo
  5. Lea la memoria en la dirección formada al reemplazar la mitad superior con el resultado ALU [$ 1334]

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).

Recuerdo haber visto algunos anuncios de computadoras con procesadores de 8 bits y 1 megabyte de memoria. Esto se hizo usando dos registros de 8 bits en la CPU más un registro de 8 bits que no está en la CPU para formar la dirección completa.
@user6030: Hay muchas formas de lograr tales cosas. Por lo general, partes del espacio de direcciones serán "fijas" y otras serán seleccionables por el banco. Algunos dispositivos funcionan muy bien para los programadores; muchos otros, no tanto.

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.