How to get CPUID using ML64 Assembly and C++ in Visual Studio IDE

Started by hasanbacioglu, October 12, 2011, 05:48:05 PM

Previous topic - Next topic

hasanbacioglu

Hi guys,
  I am trying to compile a CPUID console application using Visual Studio 2010. I have 2 files in my solution explorer. GetCpuId.asm and GetCpuId.cpp, which are like following.

;GetCpuId on x64 Window 7 Ultimate
   .code
;void getcpuid(unsigned __int32* cpuinfo,char* vendorstr);

GetCpuId   proc
   push   rbp
   mov      rbp,rsp
   mov      r8,rcx     ; capture the first and second arguments into 1->r8 and 2->r9
   mov      r9,rdx  ; cause cpuid will obliterate the lower half of those regs
   ;retrive the vendor string in its 3 parts
   mov      eax,0
   cpuid
   mov      [r9+0],ebx
   mov      [r9+4],edx
   mov      [r9+8],ecx

   mov      eax,1
   cpuid
   mov      [r8],eax
   mov      eax,0
   leave
   ret
GetCpuId   endp

end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <iostream>
#include <conio.h>

using namespace std;

extern "C" int GetCpuId(unsigned __int32* cpuinfo, char* vendorstr);

int main(int argc,char **argv){

   char vendor[13]={0};
   unsigned __int32 flags;

   if (!GetCpuId(&flags, vendor)){
      cout << "CpuId values has been successfully retrieved from ASM file."
          << endl;
      cout << "Those CpuID values comes from an external ASM file assembled with ml64.exe"
          << "linked and compiled with cl.exe within Visual Studio 2010 Ultimate Edition."
          << endl;
      cout << "Flags: %u, Vendor: %s\n", flags, vendor;
   }
   else
   {
      cout << "CpuId values cannot be retrieved !!!" << endl;
   }

   _getch();

   return 0;
}
----------------------------------------------------------------------------------------------------------------------
and ERRORS I SEE ON OUTPUT SCREEN
ml.exe /c /nologo /Zi /Fo"Debug\GetCpuId.obj" /W3 /errorReport:prompt  /Ta"GetCpuId.asm"
1> 
1>  C:\Users\TrueFX\Documents\Visual Studio 2010\Projects\Deneme\Deneme>ml.exe /c /nologo /Zi /Fo"Debug\GetCpuId.obj" /W3 /errorReport:prompt  /Ta"GetCpuId.asm"
1>   Assembling: GetCpuId.asm
1>GetCpuId.asm(2): error A2013: .MODEL must precede this directive
1>GetCpuId.asm(5): error A2034: must be in segment block : GetCpuId
1>GetCpuId.asm(6): error A2034: must be in segment block
1>GetCpuId.asm(7): error A2034: must be in segment block
1>GetCpuId.asm(8): error A2034: must be in segment block
1>GetCpuId.asm(9): error A2034: must be in segment block
1>GetCpuId.asm(11): error A2034: must be in segment block
1>GetCpuId.asm(12): error A2034: must be in segment block
1>GetCpuId.asm(13): error A2034: must be in segment block
1>GetCpuId.asm(14): error A2034: must be in segment block
1>GetCpuId.asm(15): error A2034: must be in segment block
1>GetCpuId.asm(17): error A2034: must be in segment block
1>GetCpuId.asm(18): error A2034: must be in segment block
1>GetCpuId.asm(19): error A2034: must be in segment block
1>GetCpuId.asm(20): error A2034: must be in segment block
1>GetCpuId.asm(21): error A2034: must be in segment block
1>GetCpuId.asm(22): error A2034: must be in segment block
1>GetCpuId.asm(23): fatal error A1010: unmatched block nesting : GetCpuId
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\BuildCustomizations\masm.targets(49,5): error MSB3721: The command "ml.exe /c /nologo /Zi /Fo"Debug\GetCpuId.obj" /W3 /errorReport:prompt  /Ta"GetCpuId.asm"" exited with code 1.
1>Done executing task "MASM" -- FAILED.
1>Done building target "_MASM" in project "Deneme.vcxproj" -- FAILED.
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:00.26
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
----------------------------------------------------------------------------------------------------------------------------------------

Any help ?

Thanks in advance,

Ok guys. I have tried to assemble GetCpuId.asm file using ml64.exe from command line. I have used same switches as in Visual Studio. Then its compiled and linked without error. But not in Visual Studio. I have realized that Visual Studio tries to compile asm file using ml.exe not ml64.exe. So I have changed project settings from Debug win32 to Debug x64. Now I have another problem probably related with my calling convention or something.
Here is the NEW ERROR MESSAGE I get in visual studio.

1>  "x64\Debug\GetCpuId.obj"
1>  "x64\Debug\GetCpuId.obj"
1>x64\Debug\GetCpuId.obj : warning LNK4042: object specified more than once; extras ignored
1>GetCpuId.obj : error LNK2019: unresolved external symbol GetCpuId referenced in function main
1>C:\Users\TrueFX\Documents\Visual Studio 2010\Projects\Deneme\x64\Debug\Deneme.exe : fatal error LNK1120: 1 unresolved externals
1>  The command exited with code 1120.
1>Done executing task "Link" -- FAILED.
1>Done building target "Link" in project "Deneme.vcxproj" -- FAILED.
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:03.87
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

dedndave

interesting to see 64-bit code for CPUID   :U

the segment block errors are usually generated because you failed to open a .DATA/.DATA? segment for data or .CODE segment for code
because you have that, it is probably because you have failed to define a model and a processor, so the segment doesn't open

the first error in the list tells you where the trouble lies
1>GetCpuId.asm(2): error A2013: .MODEL must precede this directive

clive

QuoteGetCpuId.asm and GetCpuId.cpp
Wouldn't you want to get more creative than that? Both of these would create a GetCpuId.obj
It could be a random act of randomness. Those happen a lot as well.

qWord

FPU in a trice: SmplMath
It's that simple!

hasanbacioglu

Quote from: clive on October 12, 2011, 06:01:10 PM
QuoteGetCpuId.asm and GetCpuId.cpp
Wouldn't you want to get more creative than that? Both of these would create a GetCpuId.obj

:) Thanks a lot. In fact I had just changed those file names to same  thing and that produced an error in compilation. Anyway your sarcastic remark has helped me to remove this error immediately :). Now it works. Thanks again.

Regards,

clive

Quote from: hasanbaciogluyour sarcastic remark

<G> That's my old cantankerous English side showing up.
It could be a random act of randomness. Those happen a lot as well.

dedndave



evlncrn8


get_cpu_vendor_information proc PUBLIC uses rax rbx rcx rdx rsi, bufferpointer:LPVOID

; assumption -> rcx = pointer to the buffer to store the data into

xor eax,eax
CPUID

mov rsi, [bufferpointer]

mov [rsi], eax
mov [rsi + 4], ebx
mov [rsi + 08h], edx
mov [rsi + 0ch], ecx

xor eax, eax
mov [rsi + 10h], eax

ret

get_cpu_vendor_information endp


is how i do it.. easy to maintain... works fine in masm32

drizz

The truth cannot be learned ... it can only be recognized.