assembly - Montaje: MOVING entre dos direcciones de memoria.
x86 instructions (5)
Estoy tratando de aprender ensamblaje (así que ten paciencia) y obtengo un error de compilación en esta línea:
mov byte [t_last], [t_cur]
El error es
error: invalid combination of opcode and operands
Sospecho que la causa de este error es simplemente que no es posible que una instrucción de movimiento se mueva entre dos direcciones de memoria, pero media hora de búsqueda en Google y no he podido confirmar esto, ¿es este el caso?
Además, suponiendo que tengo razón, significa que necesito utilizar un registro como punto intermedio para copiar la memoria:
mov cl, [t_cur]
mov [t_last], cl
¿Cuál es el registro recomendado para usar (o debo usar la pila en su lugar)?
Es realmente simple en 16 bits, solo haz lo siguiente:
push di
push si
push cx
mov cx,(number of bytes to move)
lea di,(destination address)
lea si,(source address)
rep movsb
pop cx
pop si
pop di
Nota: los pushs y pops son necesarios si necesita guardar el contenido de los registros.
Eso es correcto, el código de máquina x86 no puede codificar una instrucción con dos operandos de memoria explícitos (direcciones arbitrarias especificadas en []
)
- ¿Por qué no se permite mover de memoria a memoria?
- ¿Qué instrucciones x86 toman dos (o más) operandos de memoria?
¿Cuál es el registro recomendado?
Cualquier registro que no necesite guardar / restaurar.
En todas las convenciones de llamadas principales de 32 y 64 bits, EAX, ECX y EDX están bloqueados, por lo que AL, CL y DL son buenas opciones. En el modo de 64 bits, SIL, DIL, r8b, r9b, etc., también son opciones de búsqueda, pero requieren un prefijo REX en el código de la máquina, por lo que hay una pequeña razón de tamaño de código para evitarlos.
En general, evite escribir AH, BH, CH o DH por razones de rendimiento, a menos que haya leído y comprendido los siguientes enlaces y las dependencias falsas o las paradas de combinación de registros parciales no serán un problema o sucederán en su código. .
- ¿Por qué GCC no usa registros parciales?
- ¿Cómo funcionan exactamente los registros parciales en Haswell / Skylake? Escribir AL parece tener una dependencia falsa en RAX, y AH es inconsistente
(o debo usar la pila en su lugar)?
En primer lugar, no puede insertar un solo byte en absoluto, por lo que no hay forma de que pueda hacer un byte de carga / byte desde la pila. Para una palabra, dword o qword (dependiendo del modo de CPU), puede push [src]
/ pop [dst]
, pero eso es mucho más lento que copiar a través de un registro. Introduce una latencia de reenvío de almacenamiento de almacenamiento / recarga adicional antes de que los datos puedan leerse desde el destino final, y toma más uops.
A menos que en algún lugar de la pila esté el destino deseado y no pueda optimizar esa variable local en un registro, en cuyo caso, push [src]
está bien para copiarlo allí y asignarle espacio de pila.
Consulte https://agner.org/optimize/ y otros enlaces de rendimiento x86 en la etiqueta wiki x86
Sólo quiero hablar de "barrera de la memoria" con usted. En c codigo
a = b;//Take data from b and puts it in a
sería ensamblado para
mov %eax, b # suppose %eax is used as the temp
mov a, %eax
El sistema no puede garantizar la atomicidad de la asignación. Por eso necesitamos un rmb (leer barrera)
También hay un comando MOVS para mover datos de la memoria a la memoria:
MOV SI, OFFSET variable1
MOV DI, OFFSET variable2
MOVS
Tu sospecha es correcta, no puedes pasar de la memoria a la memoria.
Cualquier registro de propósito general hará. Recuerde PULSAR el registro si no está seguro de lo que hay dentro y restablecerlo una vez hecho.