1

我已经在这里问过类似的问题,但我仍然遇到一些错误,所以我希望你能告诉我我做错了什么。只知道我懂汇编,而且我在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 呢?

4

2 回答 2

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

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

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

如果您正在使用内联汇编程序,最好在调试器中打开 Registers 窗口并观察单步执行时情况如何变化。

您也可以直接寻址内存:

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

但是,与前面示例中的索引寻址相比,这样的直接寻址需要更多的代码字节。

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

于 2010-11-06T17:18:48.420 回答
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 窗口并检查 Hexadecimal Display 来将 Value 设置为 Hexadecimal。

于 2011-07-20T08:59:31.773 回答