MSIL aka CIL, in cui il codice sorgente C # è digerito, ha codici opcode per tre varianti su "multiply"; "mul", "mul.ovf" e "mul.ovf.un". Questi sono usati per la maggior parte dei tipi di valore incorporati, da byte a doppio. Traducono abbastanza direttamente in comandi nativi simili.
Il primo codice è di uso generale; value1 e value2 vengono inseriti nello stack di valutazione, quindi viene chiamato "mul"; value1 e value2 vengono spuntati, moltiplicati e il risultato viene inviato allo stack di valutazione. Le due varianti sono solo per la moltiplicazione intera e definiscono il comportamento di overflow "controllato"; "mul.ovf" afferma che il valore del risultato firmato si adatta al tipo di risultato determinato senza overflow, mentre "mul.ovf.un" asserisce che il valore senza segno si adatta al tipo di risultato.
Il comando "mul", come la maggior parte degli opcode, produce un risultato di un tipo basato sulle specifiche; le regole di base sono che l'operazione è definita per due input, entrambi devono essere dello stesso tipo e uno dei seguenti: int32, uint32, int64, uint64, float o double. Per la moltiplicazione di tipi diversi, o tipi non presenti nell'elenco come byte, sbyte e short, viene eseguita una conversione di allargamento sul valore della dimensione più piccola o precisione rispetto a quella del più grande (o al minimo). Questo accade praticamente di default per i tipi di interi più piccoli; la CPU non si occuperà di qualcosa di più piccolo di una parola (16 bit), e alcuni non si occuperanno più di meno di una dword contemporaneamente, quindi l'implementazione CLR semplicemente alimenterà i valori più piccoli alla CPU come password.
Giù al livello nativo, ci sono due comandi di base nell'assemblatore 80x86 per eseguire la moltiplicazione sugli stessi tipi di base: "MUL" moltiplicherà ogni due numeri interi (usando word, dword o word64 lengths), mettendo il risultato in una certa lunghezza variante indipendente del registro AXE, mentre FMUL e FMULP eseguono l'operazione equivalente su tipi in virgola mobile utilizzando la FPU del chip, eventualmente facendo scoppiare il risultato fuori dallo stack eval della FPU nel registro AX.
Per quanto riguarda esattamente quale algoritmo binario viene utilizzato per arrivare alla risposta prodotta dai comandi, non dovresti davvero preoccuparti; qualunque cosa venga utilizzata, puoi essere certo che è molto più performante di qualsiasi altra cosa tu possa fare nel codice sorgente gestito.
Ora, per i tipi di struttura più grandi, come Decimal e BigInteger, le operazioni di moltiplicazione native incorporate non esistono e quei tipi do si basano su algoritmi di moltiplicazione. Ecco il codice per BigInteger, implementato in un helper nascosto BigIntegerBuilder: link . Decimal usa una chiamata a FCallMultiply; sfortunatamente questo è un metodo esterno che lega gli MFC quindi non riesco a trovare il codice sorgente.