Search code examples
visual-c++assemblyx86inline-assemblycpuid

Some inline assembler questions


I already asked similar question here, but I still get some errors, so I hope you could tell me what am I doing wrong. Just know that I know assembler, and I have done several projects in 8051 assembler, and even it is not the same, is close to x86 asm.

There is block of code I tried in VC++ 2010 Express (I am trying to get information from CPUID instruction): `

int main()
{
char a[17]; //containing array for the CPUID string
a[16] = '\0'; //null termination for the std::cout
void *b=&a[0]; 
int c=0; //predefined value which need to be loaded into eax before cpuid

_asm
{
    mov eax,c;
    cpuid;
    mov [b],eax;
    mov [b+4],ebx;
    mov [b+8],ecx;
    mov [b+12],edx;
}
std::cout<<a;
}`

So, to quick summarize, I tried to create void pointer to the first element of array, and than using indirect addressing just move values from registers. But this approach gives me "stack around b variable is corrupted run-time error" but I don´t know why.

Please help. Thanks. And this is just for study purposes, i know there are functions for CPUID....

EDIT: Also, how can you use direct addressing in x86 VC++ 2010 inline assembler? I mean common syntax for immediate number load in 8051 is mov src,#number but in VC++ asm its mov dest,number without # sign. So how to tell the compiler you want to access memory cell adress x directly?


Solution

  • The reason your stack is corrupted is because you're storing the value of eax in b. Then storing the value of ebx at the memory location b+4, etc. The inline assembler syntax [b+4] is equivalent to the C++ expression &(b+4), if b were a byte pointer.

    You can see this if you watch b and single-step. As soon as you execute mov [b],eax, the value of b changes.

    One way to fix the problem is to load the value of b into an index register and use indexed addressing:

    mov edi,[b]
    mov [edi],eax
    mov [edi+4],ebx
    mov [edi+8],ecx
    mov [edi+12],edx
    

    You don't really need b at all, to hold a pointer to a. You can load the index register directly with the lea (load effective address) instruction:

    lea edi,a
    mov [edi],eax
    ... etc ...
    

    If you're fiddling with inline assembler, it's a good idea to open the Registers window in the debugger and watch how things change when you're single stepping.

    You can also directly address the memory:

    mov dword ptr a,eax
    mov dword ptr a+4,ebx
    ... etc ...
    

    However, direct addressing like that required more code bytes than the indexed addressing in the previous example.

    I think the above, with the lea (Load Effective Address) instruction and the direct addressing I showed answers your final question.