我已经在这里问了类似的问题,但我仍然遇到一些错误,所以我希望你能告诉我我做错了什么。只知道我知道汇编程序,并且我在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?
答案 0 :(得分:6)
您的堆栈损坏的原因是您将eax
的值存储在b
中。然后将ebx
的值存储在内存位置b+4
等。如果[b+4]
是&(b+4)
,则内联汇编语法b
等同于C ++表达式b
一个字节指针。
如果您观看mov [b],eax
并且单步执行,则可以看到此消息。只要您执行b
,b
的值就会更改。
解决问题的一种方法是将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窗口并选中十六进制显示来将值设置为十六进制。