¿Usando LEA en valores que no son direcciones / punteros?

4 minutos de lectura

avatar de usuario
Pasando por

Estaba tratando de entender cómo funciona la instrucción de cálculo de direcciones, especialmente con leaq dominio. Luego me confundo cuando veo ejemplos usando leaq para hacer cálculos aritméticos. Por ejemplo, el siguiente código C,

long m12(long x) {
return x*12;
}

En asamblea,

leaq (%rdi, %rdi, 2), %rax
salq $2, $rax

Si mi entendimiento es correcto, leaq debería mudarse a cualquier dirección (%rdi, %rdi, 2)que debe ser 2*%rdi+%rdievaluar a en %rax. Lo que me confunde es que el valor x se almacena en %rdique es solo una dirección de memoria, ¿por qué multiplica %rdi por 3 y luego cambia a la izquierda? dirección de memoria por 2 es igual a x por 12? ¿No es eso cuando tenemos tiempos? %rdi por 3, saltamos a otra dirección de memoria que no tiene el valor x?

  • @Johan, cerré stackoverflow.com/questions/13517083/… como un duplicado de esto, ya que tiene respuestas que dan más detalles para aclarar la confusión de los novatos sobre el uso de LEA con no punteros.

    – Peter Cordes

    06/10/2017 a las 21:32

  • Relacionado: ¿Cuál es el propósito de la instrucción LEA? es sobre todo preguntando por lea contra mov, que se acerca a la misma pregunta desde la dirección opuesta. Todas las respuestas allí hablan sobre usarlo para direcciones/punteros, o simplemente dicen “es un nombre estúpido para una instrucción de cambiar y agregar”, las cuales solo cuentan la mitad de la historia.

    – Peter Cordes

    06/10/2017 a las 21:41

  • ¿Estaría de acuerdo en que en la página del manual de LEA a la que se vinculó, el segundo comentario en el siguiente texto (bajo “operación”) es un error de copiar/pegar: ELSE IF OperandSize = 32 and AddressSize = 64 THEN temp ← EffectiveAddress(SRC); (* 64-bit address *) DEST ← temp[0:31]; (* 16-bit address *) FI; porque temp[0:31] es una dirección de 32 bits, no una dirección de 16 bits?

    – Peter – Reincorporar a Mónica

    6 de febrero a las 16:32


  • Sí, debería ser 32-bit address. Además, parece que falta un caso para tamaño de dirección de 32 bits, tamaño de operando de 64 bits como lea rax, [edi - 1], si van a catalogar explícitamente todos los demás combos. (Ese es totalmente inútil, sin embargo, porque es idéntico a lea eax, [rdi - 1] (que no requiere ningún prefijo), porque ambos son de extensión cero, no de signo).

    – Peter Cordes

    6 de febrero a las 16:43


  • Bueno, gracias. Eso es un poco vergonzoso porque los anchos son de lo que se trata, incluso si es solo un comentario. Acabo de verificar: el pasaje se copia literalmente del manual de Intel (el enlace es demasiado largo para un comentario, pero se encuentra en intel.com/content/www/us/en/developer/articles/technical/…). El error también está presente allí, en el vol. 2A, página 3-581

    – Peter – Reincorporar a Mónica

    6 de febrero a las 17:05


  • @Peter-ReinstateMonica: Sí, felixcloutier.com/x86 y sitios similares como github.com/HJLebbink/asm-dude/wiki se extraen del manual en PDF vol.2 de Intel. (Ambos con versiones similares del mismo script). Ese no es el primer error que se encuentra en los manuales de Intel, y tampoco el más grave.

    – Peter Cordes

    6 de febrero a las 17:08


  • Entonces, si pasamos x como 1. Supongamos que el registro es de 4 bits, ¿%rdi será 0001 o 0x1? (Si ignoramos tipo largo)

    – Pasando por

    6 de octubre de 2017 a las 2:13


  • Yo diría que eso no es un abuso de LEA, copiar y agregar es uno de los propósitos previstos de exponer la capacidad de generación de direcciones de la CPU a través de la lea instrucción. Mira mi respuesta.

    – Peter Cordes

    6 de octubre de 2017 a las 2:43

  • @ZhiyuanRuan sí, tipos como int/short/long/... son en común x86-64 ABI pasados ​​por valor, el valor en sí está en el registro cuando se llama a alguna función de manera conforme a ABI. Ninguna dirección de memoria está involucrada en su ensamblaje original del compilador.

    – Ped7g

    6 de octubre de 2017 a las 4:33

  • @PeterCordes: “abuso” se relaciona principalmente con la terminología utilizada para describir la instrucción (cargar dirección efectiva); está diseñado para la generación de direcciones, pero los registros son registros, y las matemáticas son las mismas de cualquier manera. no digo que sea malo usar leasimplemente no cuál el nombre de la instrucción le haría creer que era el propósito.

    – ShadowRanger

    6 oct 2017 a las 10:32

  • Ahí es donde no estoy de acuerdo. Creo que está diseñado para exponer la funcionalidad de generación de direcciones del hardware para su uso con fines arbitrarios. Así es como lo piensan los compiladores, y también deberían hacerlo los humanos. El nombre solo está relacionado con el hecho de que utiliza la sintaxis del modo de direccionamiento y la codificación de la máquina, no el propósito “previsto”. (Realmente no sé qué tenía Intel en mente, como dije en mi respuesta, pero creo que explicarlo a los principiantes de esta manera hace que suene normal usar LEA, porque es normal. Es por eso que no me gusta el término “abuso”, pero esa es una justificación justa para usarlo).

    – Peter Cordes

    06/10/2017 a las 10:40


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad