Domanda

In Assembler posso utilizzare il comando MUL e ottenere un EAX Risultato 64 bit: EDX, Come posso fare lo stesso in C? http://siyobik.info/index.php?module=x86&id=210

Il mio approccio di utilizzare un uint64_t e spostare il risultato non funzionano ^^

Grazie per il vostro aiuto (=

Me

È stato utile?

Soluzione

Ogni compilatore decente solo farlo quando richiesto.

Ad esempio, utilizzando VC ++ 2010, il seguente codice:

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

result = (unsigned long long)a * b ;

genera il seguente assembler:

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

Altri suggerimenti

Inserisci un codice. Questo funziona per me:

#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;
}

Vedere se è possibile ottenere l'equivalente di __emul o __emulu il compilatore (o semplicemente utilizzare questo se hai un compilatore MS). anche se a 64 bit si moltiplicano dovrebbe automaticamente il lavoro a meno che la seduta dietro qualche limitazione o altro problema divertenti (come _aulmul)

Si vuol dire moltiplicare due a 32 bit quantità per ottenere un risultato a 64 bit?

Questo non è prevista C per sé, o si hanno traino 32 bit come uint32_t e quindi il risultato è la stessa larghezza. Oppure si lanci prima di uint64_t, ma poi si perde il vantaggio di quella speciale (e veloce) si moltiplicano.

L'unico modo che vedo è quello di utilizzare le estensioni assembler in linea. gcc è abbastanza buono in questo, è possibile produrre codice proprio ottimale. Ma questo non è portabile tra diverse versioni di compilatori. (Molti compilatori di pubblico dominio adottano la gcc, però, credo)

#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. */
}

Questo produce:

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

Quando viene compilato con:

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

Il che utilizza l'istruzione mul (chiamato mull qui per moltiplicare lunga, che è come l'assemblatore GNU per x86 piace) nel modo in cui si desidera.

In questo caso uno dei parametri è stato tirato direttamente dalla pila anziché collocato in un registro (i 4(%esp) cosa mezzi 4 byte sopra lo stack pointer, e 4 byte di essere saltata sono l'indirizzo di ritorno) perché i numeri erano trasmessa alla funzione e sarebbe stato inserito nello stack (come da 86 ABI (interfaccia binaria)).

:

Se si inline la funzione o appena fatto la matematica in esso nel codice che sarebbe risultato più probabile in utilizzando l'istruzione mul in molti casi, anche se i compilatori di ottimizzazione possono anche sostituire alcuni moltiplicazioni con codice più semplice se si può dire che sarebbe lavoro (ad esempio potrebbe trasformare questo in uno spostamento o una costante se l'uno o più degli argomenti erano noti).

Nel codice C almeno uno degli argomenti dovevano essere gettato in un valore a 64 bit in modo che il compilatore produrrebbe un risultato a 64 bit. Anche se il compilatore dovesse utilizzare il codice che ha prodotto un risultato a 64 bit quando moltiplicando valori a 32 bit, potrebbe non hanno considerato la metà di esso per essere importante perché secondo alle modalità di funzionamento C solito provoca un valore dello stesso tipo come il valore con la più vasta gamma di suoi componenti (tranne a volte si può sostenere che non è davvero esattamente ciò che fa).

Non si può fare esattamente questo in C, vale a dire non si può moltiplicare due valori di N-bit e ottenere un valore 2N bit come il risultato. Semantica di C moltiplicazione è diverso da quello della moltiplicazione macchina. In C l'operatore di moltiplicazione viene sempre applicata ai valori dello stesso tipo T (cosiddetto conversioni aritmetiche abituali prendono cura di questo) e produce il risultato dello stesso tipo T.

Se si esegue in trabocco sulla moltiplicazione, è necessario utilizzare un tipo più grande per gli operandi. Se non c'è nessun tipo più grande, si è fuori di fortuna (vale a dire non avete altra scelta che utilizzare l'implementazione a livello libreria di grande moltiplicazione).

Ad esempio, se il primo tipo intero della piattaforma è un tipo a 64 bit, a livello di assemblaggio sulla macchina si ha accesso al funzionamento mul produrre il risultato corretto 128 bit. A livello di lingua non si ha accesso a tale moltiplicazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top