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
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.