machine - assembly language tutorial
¿Por qué IA32 no permite mover la memoria a la memoria? (4)
En la arquitectura Intel IA32, las instrucciones como movl, movw no permiten los operandos que son ambas ubicaciones de memoria. Por ejemplo, la instrucción movl (% eax), (% edx) no está permitida. ¿Por qué?
Hasta donde yo sé, como regla general en esta arquitectura, solo se permite un acceso a memoria por instrucción. Esto se debe a que lidiar con dos accesos de memoria por instrucción complicaría la línea de ejecución del procesador.
La respuesta implica una comprensión más completa de RAM. En pocas palabras, la RAM solo puede estar en dos estados, modo de lectura o modo de escritura. Si desea copiar un byte en ram a otra ubicación, debe tener un área de almacenamiento temporal fuera de la RAM cuando cambie de lectura a escritura.
Ciertamente es posible que la arquitectura tenga dicha instrucción de RAM a RAM, pero sería una instrucción de alto nivel que en microcódigo se traduciría en copia de datos de RAM a un registro y luego a RAM. Alternativamente, podría ser posible extender el controlador RAM para tener un registro temporal tal solo para esta copia de datos, pero no proporcionaría mucho beneficio para la complejidad añadida de la interacción CPU / Hardware.
EDIT: Vale la pena señalar que avances recientes como Hybrid Memory Cube y High Bandwidth Memory son logros en los que la topología de la RAM se parece más a PCI-e y ahora son posibles transferencias directas de RAM a RAM, pero eso se debe a la lógica de soporte para las tecnologías, no la RAM en sí. En la arquitectura de la CPU, esto sería en forma de grandes bloques de RAM a la vez, como DMA, y no en forma de una sola instrucción, además la memoria caché de la CPU se comporta como la RAM tradicional, por lo que la arquitectura tendría que abstraerla como por mi explicación original
EDIT2: por el comentario de @PeterCordes, mi comprensión original no era del todo correcta; x86 de hecho tiene algunas instrucciones de memoria a memoria. La verdadera razón por la que no están disponibles para la mayoría de las instrucciones (como movl y movw) es mantener la complejidad de la codificación de instrucciones baja, pero podrían haberlas implementado. Sin embargo, la idea básica en mi respuesta original, que hay una ubicación de almacenamiento temporal fuera de la RAM en forma de un pestillo o registro, es correcta, pero la idea de que esta es la razón por la cual estas instrucciones no existen no lo es. Incluso chips más antiguos de la década de 1970, como el 6502 y el 8086 tienen instrucciones de memoria a memoria, y usted puede realizar fácilmente operaciones como INC directamente en una ubicación de RAM. Esto se logró enganchando la recuperación de memoria directamente a la ALU y volviendo a la memoria sin pasar por un registro utilizado por el conjunto de instrucciones.
RAM admite entrada y salida, pero no copia. Por lo tanto, un movimiento de memoria a memoria sería en realidad un movimiento de memoria a CPU a memoria. En teoría, sería posible implementar tal instrucción, pero probablemente no fue porque no sería muy práctico.
Estas son algunas de las cosas que deberían tenerse en cuenta para implementar tal instrucción:
¿Qué ubicación de almacenamiento temporal usamos? Un registro?
Si utilizamos un registro, ¿cuál de nosotros secuestramos?
No proporcionar dicha instrucción deja las preguntas anteriores en manos del programador.
ia32 es x86, y x86 es la evolución del intel 8086 (iAPX 86). Era un chip pequeño y barato basado en conjuntos de instrucciones de 8 bits, y no tenía "mov" con dos operandos de memoria explícitos.
El autor de Wikipedia da esa explicación sobre la codificación de instrucciones de 8086:
Debido a una codificación compacta inspirada en procesadores de 8 bits, la mayoría de las instrucciones son operaciones de una dirección o de dos direcciones, lo que significa que el resultado se almacena en uno de los operandos. Como máximo, uno de los operandos puede estar en la memoria, pero este operando de memoria también puede ser el destino, mientras que el otro operando, la fuente, puede ser de registro o inmediato. Una ubicación de memoria individual también se puede usar a menudo como fuente y destino, lo que, entre otros factores, contribuyó aún más a una densidad de código comparable a (ya menudo mejor que) la mayoría de las máquinas de ocho bits en ese momento.
Hubo algunos CISC con instrucciones de memoria de memoria (instrucción única para operar en dos operandos de memoria). La conferencia https://www.cis.upenn.edu/~milom/cis501-Fall05/lectures/02_isa.pdf dice que VAX puede codificar las instrucciones de la memoria de la memoria:
DEC VAX (extensión de dirección virtual a PDP-11): 1977
- • Instrucciones de longitud variable: 1-321 bytes.
- • 14 GPRs + PC + stack-pointer + códigos de condición
- • Tamaños de datos: 8, 16, 32, 64, 128 bit, decimal, cadena
- • Instrucciones de memoria de memoria para todos los tamaños de datos
- • Insns especiales: crc, insque, polyf y un elenco de cientos
Esta es la fuente de memcpy de OpenBSD para VAX (manual del conjunto de instrucciones http://h20565.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c04623178 ):
movq 8(ap),r1 /* r1 = src, r2 = length */
movl 4(ap),r3 /* r3 = dst */
...
1: /* move forward */
cmpl r2,r0
bgtru 3f /* stupid movc3 limitation */
movc3 r2,(r1),(r3) /* move it all */
La instrucción "movc3" aquí tiene dos operandos de memoria, cuyas direcciones se almacenan en registros.
x86 tiene varias instrucciones de "cadena" que harán operaciones de memoria de memoria (* s, especialmente movs - http://x86.renejeschke.de/html/file_module_x86_id_203.html ), pero esta instrucción utilizará los registros predefinidos SI y DI como direcciones (operandos implícitos), y dos operandos de memoria aún no se pueden codificar en x86.