一些内联汇编程序问题

时间:2010-11-06 15:47:06

标签: visual-c++ assembly x86 inline-assembly 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;
}`

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

请帮忙。谢谢。这只是出于学习目的,我知道CPUID有函数....

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

2 个答案:

答案 0 :(得分:6)

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

如果您观看mov [b],eax并且单步执行,则可以看到此消息。只要您执行bb的值就会更改。

解决问题的一种方法是将mov edi,[b] mov [edi],eax mov [edi+4],ebx mov [edi+8],ecx mov [edi+12],edx 的值加载到索引寄存器中并使用索引编址:

b

你根本不需要a来保持指向lea的指针。您可以使用lea edi,a mov [edi],eax ... etc ... (加载有效地址)指令直接加载索引寄存器:

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

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

您也可以直接寻址内存:

lea

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

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

答案 1 :(得分:0)

在调试器中打开Registers窗口的建议观察事情如何变化在VC ++ 2010 Express中不起作用。

你可能会发现VC ++ 2010 Express正在错过寄存器窗口,这和我一样惊讶。自从踩踏拆卸工作以来,这一点尤其令人惊讶。

我知道的唯一解决方法是打开监视窗口并在“名称”字段中键入寄存器名称。如果需要,请输入EAX EBX ECX EDX ESI EDI EIP ESP EBP EFL和CS DS ES SS FS GS

ST1 ST2 ST3 ST4 ST5 ST6 ST7也可在手表窗口工作。

您可能还需要通过右键单击Watch窗口并选中十六进制显示来将值设置为十六进制。