There are a lot of questions about this on StackOverflow. A lot. However I cannot find an answer that:
Since we're talking about .NET here, it's usually preferable not to resort to external native calls. But if you can tolerate the overhead of a managed/unmanaged roundtrip for each operation, the following two calls provide pretty direct and unadulterated access to the native CPU instructions.
The (minimalistic) disassembly of the respective entire functions from ntdll.dll are also shown for each. That library will be present on any Windows machine, and will always be found, if referenced as shown.
Least-significant bit (LSB):
[DllImport("ntdll"), SuppressUnmanagedCodeSecurity]
public static extern int RtlFindLeastSignificantBit(ulong ul);
// X64:
// bsf rdx, rcx
// mov eax, 0FFFFFFFFh
// movzx ecx, dl
// cmovne eax,ecx
// ret
Most-significant bit (MSB):
[DllImport("ntdll"), SuppressUnmanagedCodeSecurity]
public static extern int RtlFindMostSignificantBit(ulong ul);
// X64:
// bsr rdx, rcx
// mov eax, 0FFFFFFFFh
// movzx ecx, dl
// cmovne eax,ecx
// ret
Usage:
Here's a usage example which requires that the above declarations be accessible. Couldn't be simpler.
int ix;
ix = RtlFindLeastSignificantBit(0x00103F0A042C1D80UL); // ix --> 7
ix = RtlFindMostSignificantBit(0x00103F0A042C1D80UL); // ix --> 52