MSIL aka CIL, into which C# source code is digested, has opcodes for three variations on "multiply"; "mul", "mul.ovf", and "mul.ovf.un". These are used for most built-in value types, from byte to double. They translate pretty directly down to similar native commands.
The first code is general-purpose; value1 and value2 are pushed onto the evaluation stack, then "mul" is called; value1 and value2 are popped, multiplied, and the result is pushed to the evaluation stack. The two variations are for integer multiplication only, and define "checked" overflow behavior; "mul.ovf" asserts that the signed result value will fit into the determined result type without overflow, while "mul.ovf.un" asserts that the unsigned value will fit into the result type.
The "mul" command, like most opcodes, produces a result of a type based on the specifications; the basic rules are that the operation is defined for two inputs, both of which must be the same type and one of the following: int32, uint32, int64, uint64, float, or double. For multiplication of differing types, or types not in the list such as byte, sbyte and short, a widening conversion is performed on the value of the smaller size or precision to that of the larger (or to the minimum). This happens pretty much by default for smaller integer types; the CPU won't deal with anything smaller than a word (16-bit), and some won't even deal with less than a dword at once anymore, so the CLR implementation will simply feed smaller values to the CPU as dwords.
Down at the native level, there are two basic commands in 80x86 assembler to perform multiplication on the same basic types: "MUL" will multiply any two integers (using word, dword or word64 lengths), putting the result in some length-dependent variant of the AX register, while FMUL and FMULP perform the equivalent operation on floating-point types using the chip's FPU, optionally popping the result off of the FPU's eval stack into the AX register.
As far as exactly which binary algorithm is used to arrive at the answer produced by the commands, you really shouldn't care; whatever's used, you can be sure it's much more performant than anything you could do in managed source code.
Now, for larger structural types, like Decimal and BigInteger, built-in native multiplication operations don't exist, and those types do rely on multiplication algorithms. Here's the code for BigInteger, implemented in a hidden helper BigIntegerBuilder: http://typedescriptor.net/name/types/8FF4E74C7553501B0863FF102EC0C5B1-System.Numerics.BigIntegerBuilder. Decimal uses a call to FCallMultiply; unfortunately that's an extern method tying into the MFCs so I can't find source code.
2 * 3
orMath.Pi * 2.0
?FCallMultiply
). However, if you want to see some framework multiplication, check outRefSrc\Source\.Net\4.0\DEVDIV_TFS\Dev10\Releases\RTMRel\ndp\fx\src\security\system\security\cryptography\BigInt.cs
within .Net 4+ on referencesource.microsoft.com/netframework.aspx . The code is exactly what you would expect.