suma resta registros numeros multiplicar multiplicacion multiplica lenguaje ensamblador digitos como assembly x86

assembly - resta - ¿Cómo puedo multiplicar dos números de 64 bits utilizando el lenguaje de ensamblaje x86?



resta de 2 numeros en ensamblador (12)

¿Cómo voy a ir ...

  • multiplicando dos números de 64 bits

  • multiplicando dos números hexadecimales de 16 dígitos

... usando el lenguaje ensamblador.

Solo puedo usar los registros% eax,% ebx,% ecx,% edx y la pila.

EDITAR: Oh, estoy usando sintaxis ATT en el x86
EDIT2: no se permite descompilar en ensamblaje ...


Si quieres el modo 128 prueba esto ...

__uint128_t AES::XMULTX(__uint128_t TA,__uint128_t TB) { union { __uint128_t WHOLE; struct { unsigned long long int LWORDS[2]; } SPLIT; } KEY; register unsigned long long int __XRBX,__XRCX,__XRSI,__XRDI; __uint128_t RESULT; KEY.WHOLE=TA; __XRSI=KEY.SPLIT.LWORDS[0]; __XRDI=KEY.SPLIT.LWORDS[1]; KEY.WHOLE=TB; __XRBX=KEY.SPLIT.LWORDS[0]; __XRCX=KEY.SPLIT.LWORDS[1]; __asm__ __volatile__( "movq %0, %%rsi /n/t" "movq %1, %%rdi /n/t" "movq %2, %%rbx /n/t" "movq %3, %%rcx /n/t" "movq %%rdi, %%rax /n/t" "mulq %%rbx /n/t" "xchgq %%rbx, %%rax /n/t" "mulq %%rsi /n/t" "xchgq %%rax, %%rsi /n/t" "addq %%rdx, %%rbx /n/t" "mulq %%rcx /n/t" "addq %%rax, %%rbx /n/t" "movq %%rsi, %0 /n/t" "movq %%rbx, %1 /n/t" : "=m" (__XRSI), "=m" (__XRBX) : "m" (__XRSI), "m" (__XRDI), "m" (__XRBX), "m" (__XRCX) : "rax","rbx","rcx","rdx","rsi","rdi" ); KEY.SPLIT.LWORDS[0]=__XRSI; KEY.SPLIT.LWORDS[1]=__XRBX; RESULT=KEY.WHOLE; return RESULT; }


Apuesto a que eres estudiante, así que mira si puedes hacer que esto funcione: hazlo palabra por palabra y usa los cambios de bit. Piensa en la solución más eficiente. Cuidado con el bit de signo.


Depende del idioma que estés usando. Por lo que recuerdo al aprender a ensamblar MIPS, hay un comando Mover desde alto y un comando Mover desde Lo, o mflo y mfhi. mfhi almacena los 64 bits superiores mientras que mflo almacena los 64 bits más bajos del número total.


Es posible que desee especificar qué ensamblaje está utilizando. Las técnicas generales son aplicables de forma cruzada (generalmente), pero los mnemónicos son casi siempre diferentes entre plataformas. :-)


Simplemente haga una multiplicación normal larga, como si estuviera multiplicando un par de números de 2 dígitos, excepto que cada "dígito" es realmente un entero de 32 bits. Si está multiplicando dos números en las direcciones X e Y y almacenando el resultado en Z, entonces lo que quiere hacer (en el pseudocódigo) es:

Z[0..3] = X[0..3] * Y[0..3] Z[4..7] = X[0..3] * Y[4..7] + X[4..7] * Y[0..3]

Tenga en cuenta que estamos descartando los 64 bits superiores del resultado (ya que un número de 64 bits por un número de 64 bits es un número de 128 bits). También tenga en cuenta que esto está asumiendo little-endian. Además, tenga cuidado con un multiplicado firmado versus uno no firmado.


Ya que está en x86 necesita 4 instrucciones de reflexión. Divida las cantidades de 64 bits en dos palabras de 32 bits y multiplique las palabras bajas por la palabra más baja y la segunda más baja del resultado, luego ambos pares de palabra baja y alta de diferentes números (van a la segunda y tercera palabra más baja del resultado) finalmente ambas palabras altas en las 2 palabras más altas del resultado. Agrégalos a todos juntos sin olvidarte de lidiar con llevar. No especificó el diseño de memoria de las entradas y salidas por lo que es imposible escribir código de muestra.


ah ensamblaje, hace un tiempo ya que lo he usado. así que supongo que el verdadero problema aquí es que el microcontrolador (¿para qué escribí el código para el montaje de todos modos) en el que estás trabajando no tiene registros de 64 bits? si ese es el caso, vas a dividir las cantidades con las que trabajas y realizar multiplicaciones múltiples con las piezas.

esto suena como una tarea por la forma en que lo has redactado, así que no lo voy a explicar mucho más: P


Busque un compilador de C que admita 64 bits (GCC hace IIRC) compila un programa que hace justamente eso, luego obtenga el desmontaje. GCC puede escupirlo por sí mismo y puede sacarlo del archivo objeto con las herramientas adecuadas.

OTOH su es un 32bX32b = 64b op en x86

a:b * c:d = e:f // goes to e:f = b*d; x:y = a*d; e += x; x:y = b*c; e += x;

todo lo demás se desborda

(no probado)

Editar sin firmar solo


Si esto fue 64x86,

function(x, y, *lower, *higher) movq %rx,%rax #Store x into %rax mulq %y #multiplies %y to %rax #mulq stores high and low values into rax and rdx. movq %rax,(%r8) #Move low into &lower movq %rdx,(%r9) #Move high answer into &higher


Este código supone que desea x86 (no el código x64), que probablemente solo quiera un producto de 64 bits y que no le importa el desbordamiento o los números con signo. (Una versión firmada es similar).

MUL64_MEMORY: mov edi, val1high mov esi, val1low mov ecx, val2high mov ebx, val2low MUL64_EDIESI_ECXEBX: mov eax, edi mul ebx xch eax, ebx ; partial product top 32 bits mul esi xch esi, eax ; partial product lower 32 bits add ebx, edx mul ecx add ebx, eax ; final upper 32 bits ; answer here in EBX:ESI

Esto no respeta las restricciones de registro exactas de OP, pero el resultado se ajusta completamente a los registros que ofrece el x86. (Este código no ha sido probado, pero creo que es correcto).

[Nota: transferí (mi) esta respuesta de otra pregunta que se cerró, porque NINGUNA de las otras "respuestas" aquí respondió directamente la pregunta].


Use lo que probablemente sea su libro de texto del curso, "The Art of Assembly Language" de Randall Hyde.

Ver 4.2.4 - Multiplicación de precisión extendida

Aunque una multiplicación de 8x8, 16x16 o 32x32 suele ser suficiente, hay momentos en los que es posible que desee multiplicar valores más grandes juntos. Utilizará las instrucciones MULTI e IMUL de un solo operando x86 para la multiplicación de precisión extendida.

Probablemente, lo más importante que debe recordar al realizar una multiplicación de precisión extendida es que también debe realizar una adición de precisión múltiple al mismo tiempo . Agregar todos los productos parciales requiere varias adiciones que producirán el resultado. La siguiente lista muestra la forma correcta de multiplicar dos valores de 64 bits en un procesador de 32 bits.

(Consulte el enlace para obtener una lista de ensamblaje completa e ilustraciones).


Si quieres una multiplicación de 128 bits, entonces debería funcionar, está en formato AT & T.

__uint128_t FASTMUL128(const __uint128_t TA,const __uint128_t TB) { union { __uint128_t WHOLE; struct { unsigned long long int LWORDS[2]; } SPLIT; } KEY; register unsigned long long int __RAX,__RDX,__RSI,__RDI; __uint128_t RESULT; KEY.WHOLE=TA; __RAX=KEY.SPLIT.LWORDS[0]; __RDX=KEY.SPLIT.LWORDS[1]; KEY.WHOLE=TB; __RSI=KEY.SPLIT.LWORDS[0]; __RDI=KEY.SPLIT.LWORDS[1]; __asm__ __volatile__( "movq %0, %%rax /n/t" "movq %1, %%rdx /n/t" "movq %2, %%rsi /n/t" "movq %3, %%rdi /n/t" "movq %%rsi, %%rbx /n/t" "movq %%rdi, %%rcx /n/t" "movq %%rax, %%rsi /n/t" "movq %%rdx, %%rdi /n/t" "xorq %%rax, %%rax /n/t" "xorq %%rdx, %%rdx /n/t" "movq %%rdi, %%rax /n/t" "mulq %%rbx /n/t" "xchgq %%rbx, %%rax /n/t" "mulq %%rsi /n/t" "xchgq %%rax, %%rsi /n/t" "addq %%rdx, %%rbx /n/t" "mulq %%rcx /n/t" "addq %%rax, %%rbx /n/t" "movq %%rsi, %%rax /n/t" "movq %%rbx, %%rdx /n/t" "movq %%rax, %0 /n/t" "movq %%rdx, %1 /n/t" "movq %%rsi, %2 /n/t" "movq %%rdi, %3 /n/t" : "=m"(__RAX),"=m"(__RDX),"=m"(__RSI),"=m"(__RDI) : "m"(__RAX), "m"(__RDX), "m"(__RSI), "m"(__RDI) : "rax","rbx","ecx","rdx","rsi","rdi" ); KEY.SPLIT.LWORDS[0]=__RAX; KEY.SPLIT.LWORDS[1]=__RDX; RESULT=KEY.WHOLE; return RESULT; }