I did make the variable static in my class and that allowed me to compile now? Not sure why that is....
When the variable is not static, i.e. every instance of your class holds its own copy of the variable, how is the assembler supposed to know which instance you want to load? Just giving it a variable name doesn't connect the variable name to a "this" pointer.
The reason making the variable static works is because you now have one copy of the variable no matter how many instances of your class you create. Since there's only ever one, you can refer to it by name and the compiler knows what you're referring to.
Why are you even using inline asm for this? In the first place, Microsoft provides the rdtsc function as an intrinsic. Furthermore, you shouldn't be using the TSC for any sort of reliable timing. Multicore and hyperthreaded CPUs can easily skew the results (since there is no guarantee that the values for each core are synchronized), as can hibernation, power-saving measures on mobile processors, OS scheduling, and out-of-order execution. This is why the QueryPerformanceCounter function exists.
Why are you even using inline asm for this? In the first place, Microsoft provides the rdtsc function as an intrinsic. Furthermore, you shouldn't be using the TSC for any sort of reliable timing. Multicore and hyperthreaded CPUs can easily skew the results (since there is no guarantee that the values for each core are synchronized), as can hibernation, power-saving measures on mobile processors, OS scheduling, and out-of-order execution. This is why the QueryPerformanceCounter function exists.
C variables *are* memory addresses. You don't need to LEA. LEA is a misnomer, it's not used for addressing in modern 32-bit flat-memory-model programs. It's used for fast multiply-by-constant. 16-bit and 64-bit modes use it occasionally.
You don't need to zero the variables first.
You can mov directly to/from a C variable and the assembler will automatically figure out the memory operand to insert (usually an [EBP-X] or [ESP+X] if you have FPO enabled).
VC++ 2008 compiles and runs the following code for me:
int _tmain(int argc, _TCHAR* argv[])
{
unsigned int a;
unsigned int b;
One thing to note: The compiler does not properly optimize inline assembly. There's no reason for it to store eax and edx back into memory when it's just going to load them up to push them to printf.
Now, take a look at the difference when I use the intrinsic. The compiler has completely optimized out my C variable since it knows that it doesn't need it:
[source]
int _tmain(int argc, _TCHAR* argv[])
{
__int64 a = __rdtsc();
00C11000 0F 31 rdtsc
The inline won't compile in Visual Studio in x64 mode (even though every instruction used here is encodable in 64-bit mode) because it doesn't support inline assembly. The intrinsic DOES compile in x64 mode.
You'll have to #ifdef a few separate ways anyway if you're going cross-platform, since different compilers can have different intrinsics (if they have them at all...).
Also, if you target non-Windows operating systems, be aware that RDTSC can throw an exception if the kernel has restricted access by enabling the CR4.TSD flag and your code is not priv level 0. (You should really use a platform-independent library since they will take care of this for you.)