一些内联汇编程序问题

B.G*_*ill 1 x86 assembly inline-assembly visual-c++ cpuid

我已经在这里问了类似的问题,但我仍然有一些错误,所以我希望你能告诉我我做错了什么.只知道我知道汇编程序,并且我在8051汇编程序中完成了几个项目,即使它不一样,也接近于x86 asm.

我在VC++ 2010 Express中试过一段代码(我试图从CPUID指令中获取信息):`

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;
}`
Run Code Online (Sandbox Code Playgroud)

因此,为了快速总结,我尝试创建指向数组第一个元素的void指针,而不是使用间接寻址只是从寄存器移动值.但是这种方法让我"堆栈b变量是运行时错误",但我不知道为什么.

请帮忙.谢谢.这只是为了研究目的,我知道有CPUID的功能....

编辑:另外,如何在x86 VC++ 2010内联汇编程序中使用直接寻址?我的意思是8051中立即数字加载的常用语法是mov src,#numberVC++ asm,mov dest,number没有#符号.那么如何告诉编译器你想直接访问内存单元地址x?

Jim*_*hel 6

堆栈损坏的原因是因为您存储了eaxin 的值b.然后将值存储ebx在内存位置b+4等.如果是字节指针,则内联汇编语法[b+4]等效于C++表达式.&(b+4)b

如果你观看b并单步,你可以看到这一点.一旦执行mov [b],eax,就会b发生变化的价值.

解决问题的一种方法是将值加载b到索引寄存器中并使用索引编址:

mov edi,[b]
mov [edi],eax
mov [edi+4],ebx
mov [edi+8],ecx
mov [edi+12],edx
Run Code Online (Sandbox Code Playgroud)

你根本不需要b拿指针a.您可以使用lea(加载有效地址)指令直接加载索引寄存器:

lea edi,a
mov [edi],eax
... etc ...
Run Code Online (Sandbox Code Playgroud)

如果您正在摆弄内联汇编程序,最好在调试器中打开"寄存器"窗口,并观察单步执行时情况的变化.

您也可以直接寻址内存:

mov dword ptr a,eax
mov dword ptr a+4,ebx
... etc ...
Run Code Online (Sandbox Code Playgroud)

但是,直接寻址需要比前一个示例中的索引寻址更多的代码字节.

我认为,上面的lea(加载有效地址)指令和我所展示的直接寻址回答了你的最后一个问题.