Question

Dans Assembleur je peux utiliser la commande MUL et obtenir un 64 bits Résultat EAX: EDX, comment puis-je faire la même chose en C? http://siyobik.info/index.php?module=x86&id=210

Mon approche d'utiliser un uint64_t et changer le résultat ne fonctionne pas ^^

Merci pour votre aide (=

Me

Était-ce utile?

La solution

Tout compilateur décent juste faire quand on lui demande.

Par exemple en utilisant VC ++ 2010, le code suivant:

unsigned long long result ;
unsigned long a = 0x12345678 ;
unsigned long b = 0x87654321 ;

result = (unsigned long long)a * b ;

génère l'assembleur suivant:

mov         eax,dword ptr [b] 
mov         ecx,dword ptr [a] 
mul         eax,ecx 
mov         dword ptr [result],eax 
mov         dword ptr [a],edx 

Autres conseils

un peu de code. Cela fonctionne pour moi:

#include <inttypes.h>
#include <stdio.h>

int main(void) {
  uint32_t x, y;
  uint64_t z;
  x = 0x10203040;
  y = 0x3000;
  z = (uint64_t)x * y;
  printf("%016" PRIX64 "\n", z);
  return 0;
}

Voyez si vous pouvez obtenir l'équivalent de __emul ou __emulu votre compilateur (ou tout simplement utiliser si vous avez un compilateur MS). si 64bit se multiplient devrait automatiquement à moins que votre travail assis derrière une restriction ou un autre problème drôle (comme _aulmul)

signifient pour multiplier deux 32 quantités de bits pour obtenir un résultat de 64 bits?

Ce n'est pas prévu dans C par lui-même, que ce soit vous avez la remorque 32 bits tels que dans uint32_t et le résultat est de la même largeur. Ou vous lancez avant de uint64_t mais vous perdez l'avantage de cette spéciale (et rapide) se multiplient.

La seule façon que je vois est d'utiliser des extensions d'assembleur en ligne. gcc est assez bonne dans ce domaine, vous pouvez produire un code tout à fait optimale. Mais ce n'est pas portable entre les différentes versions de compilateurs. (De nombreux compilateurs du domaine public adoptent le gcc, cependant, je pense)

#include

/* The name says it all.  Multiply two 32 bit unsigned ints and get
 * one 64 bit unsigned int.
 */
uint64_t mul_U32xU32_u64(uint32_t a, uint32_t x) {
  return a * (uint64_t)b; /* Note about the cast below. */
}

produit:

mul_U32xU32_u64:
    movl    8(%esp), %eax
    mull    4(%esp)
    popl    %ebp
    ret

Lorsque compilé avec:

 gcc -m32 -O3 -fomit-frame-pointer -S mul.c

Ce qui utilise l'instruction mul (appelé mull ici pour multiplier longtemps, ce qui est de savoir comment l'assembleur pour x86 gnu aime) de la manière que vous voulez.

Dans celui-ci en cas de paramètres a été tiré directement à partir de la pile, plutôt que placé dans un registre (les moyens chose de 4(%esp) 4 octets au-dessus du pointeur de pile, et les 4 octets étant sauté sont l'adresse de retour), car les chiffres étaient transmise à la fonction et aurait été poussé sur la pile (selon le x86 ABI (Application interface binaire)).

Si vous inline la fonction ou tout simplement fait le calcul en elle dans votre code, il serait très probablement comme conséquence par l'instruction mul dans de nombreux cas, bien que l'optimisation des compilateurs peuvent également remplacer certains multiplications avec le code plus simple s'ils peuvent dire que ce serait travail (par exemple, il pourrait en faire un changement ou même une constante si l'un ou plusieurs des arguments étaient connus).

Dans le code C au moins l'un des arguments ont dû être coulé à une valeur de 64 bits de sorte que le compilateur de produire un résultat de 64 bits. Même si le compilateur a dû utiliser le code qui a produit un résultat 64 bits lors de la multiplication des valeurs 32 bits, il peut ne pas avoir considéré la moitié supérieure qu'il est important parce que, selon les règles de fonctionnement C entraîne généralement une valeur avec le même type comme la valeur la plus grande gamme de ses composants (sauf que vous pouvez parfois disputez ce n'est pas vraiment exactement ce qu'il fait).

Vous ne pouvez pas faire exactement cela en C, à savoir vous ne pouvez pas multiplier deux valeurs N bits et d'obtenir une valeur bits 2N comme résultat. Sémantique de multiplication C est différente de celle de votre multiplication de la machine. En C, l'opérateur de multiplication est toujours appliquée aux valeurs du même type T (que l'on appelle conversions arithmétiques habituelles prendre soin de cela) et produit le résultat du même type T.

Si vous rencontrez un débordement sur la multiplication, vous devez utiliser un plus grand type pour les opérandes. S'il n'y a pas plus grand type, vous êtes hors de la chance (ce que vous avez pas d'autre choix que d'utiliser la mise en œuvre au niveau de la bibliothèque de grande multiplication).

Par exemple, si le plus grand type entier de votre plate-forme est un type 64 bits, puis au niveau de l'assemblage sur votre machine, vous avez accès à l'exploitation de mul produire le résultat 128 bits correct. Au niveau de la langue que vous n'avez pas accès à une telle multiplication.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top