implementar aritmética de 64 bits en una máquina de 32 bits

4 minutos de lectura

avatar de usuario
bocado.wang

El siguiente código calcula el producto de x e y y almacena el resultado en la memoria. El tipo de datos ll_t se define como equivalente a long long.

typedef long long ll_t;
void store_prod(ll_t *dest, int x, ll_t y) {
    *dest = x*y;
}

gcc genera el siguiente código ensamblador implementando el cálculo: dest en %ebp+8, x en %ebp+12, y en %ebp+16

1 movl 16(%ebp), %esi
2 movl 12(%ebp), %eax
3 movl %eax, %edx
4 sarl $31, %edx
5 movl 20(%ebp), %ecx
6 imull %eax, %ecx
7 movl %edx, %ebx
8 imull %esi, %ebx
9 addl %ebx, %ecx
10 mull %esi
11 leal (%ecx,%edx), %edx
12 movl 8(%ebp), %ecx
13 movl %eax, (%ecx)
14 movl %edx, 4(%ecx)

Este código usa tres multiplicaciones para implementar la aritmética de precisión múltiple requerida para implementar la aritmética de 64 bits en una máquina de 32 bits. Describa el algoritmo utilizado para calcular el producto y anote el código ensamblador para mostrar cómo realiza su algoritmo.

No entiendo la línea 8 y la línea 9 en el código ensamblador anterior. ¿Alguien puede ayudar?

  • Parece que está haciendo algo muy complicado para no necesitar instrucciones de agregar con llevar …

    – Místico

    27 de julio de 2012 a las 2:47

  • @Mysticial Nada complicado. No necesita ADC cuando calcula productos truncados como es el caso aquí.

    – Alexei Frunze

    27 de julio de 2012 a las 3:57

  • Respuesta SO estándar: ¿qué has probado? De su comentario a continuación, lo que realmente está preguntando es: ¿cuál es el algoritmo? Bueno, esa es tu tarea; eso es lo que se supone que debes averiguar. ¿Qué has hecho hasta ahora en tus intentos de resolverlo? Dices que sabes lo que hacen las instrucciones… entonces tal vez empieces por escribir eso.

    –Jim Balter

    27 de julio de 2012 a las 4:00

Respuesta recomendada por Intel

  • Excelente respuesta, pero probablemente demasiado detallada para un homework etiqueta – hablando desde una perspectiva de TA aquí.

    – atomicinf

    27 de julio de 2012 a las 4:51

  • Muchas gracias, ya veo lo que pasó. El algoritmo que pensé era x * (y_high * 2^32 + y_low)(x es de 32 bits), por eso estaba confundido acerca de la línea 8 y la línea 9. Me pregunto si es necesario extender x a 64 bits.

    – bocado.wang

    27 de julio de 2012 a las 4:59

  • Descubrí por qué debería extenderse x a 64 bits.

    – bocado.wang

    27 de julio de 2012 a las 5:30


  • cdq es equivalente a mov edx, eax / sar edx,31 – extiende EAX a EDX:EAX. lea edx, [ecx + edx] bien podría ser add edx, ecx.

    – Peter Cordes

    27 de diciembre de 2020 a las 5:45

  • gracias, pero sigo sin entenderlo. ¿Por qué se debe agregar sgn(x) * (y % 2^32) a ECX? Creo que imull %eax %ecx ha hecho la mitad superior de la multiplicación.

    – bocado.wang

    27 de julio de 2012 a las 3:28

  • Buena pregunta. tienes razón en eso IMUL %eax, %ecx se ha ocupado de la mitad superior de la multiplicación, pero sgn(x) * (y % 2^32) no toca la mitad superior en absoluto. Considere los límites matemáticos de sgn(x) y foo % 2^32. También podría considerar que IMUL de dos operaciones trunca su resultado a 32 bits, aunque no creo que eso sea directamente relevante para el paso en cuestión.

    – atomicinf

    27 de julio de 2012 a las 3:32

  • sgn(x) * (y % 2^32) no toca la mitad superior en absoluto, pero su valor se agrega a ecx donde se almacena la mitad superior de la multiplicación.

    – bocado.wang

    27 de julio de 2012 a las 3:41


  • Esto es absolutamente cierto; necesitamos el valor combinado más adelante en el algoritmo, por lo que en este momento, usamos ECX como un valor intermedio esencialmente porque está ahí y ya no necesitamos la mitad superior sin procesar.

    – atomicinf

    27 de julio de 2012 a las 3:44

  • @atomicinf Creo que te refieres a “dos operandos” allí en lugar de “dos operaciones”

    – harold

    27 de julio de 2012 a las 9:04

  • El operando derecho es el destino, por lo que la línea 9 pone %ebx + %ecx en %ecx.

    –Jim Balter

    27 de julio de 2012 a las 3:08

  • este Enlace da un conocimiento profundo y considerando que es una tarea.

    – Vishal129

    27 de julio de 2012 a las 3:08

  • Ese documento no coincide con el lenguaje ensamblador de gnu… consulte stackoverflow.com/questions/2397528/…

    –Jim Balter

    27 de julio de 2012 a las 3:10


  • Gracias por su respuesta. este código es del libro cs_app segunda edición (tarea 3.55). Sé lo que significan esas instrucciones de ensamblaje, pero el algoritmo me confunde. ¿Para qué sirven las líneas 4,7,8,9?

    – bocado.wang

    27 de julio de 2012 a las 3:14

  • IMUL de dos operandos con signo: multiplica los dos operandos y almacena el resultado en el operando de destino. Acabas de describir un operando IMUL ECX.

    – atomicinf

    27 de julio de 2012 a las 3:15

¿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