【发布时间】:2012-01-30 19:12:24
【问题描述】:
所以对于任何精通汇编的人来说,这似乎都是一个非常简单的问题,但我希望有人可以向我解释以下两段代码之间的区别,因为其中一段会导致分段错误并且另一个没有,但(对我而言)它们似乎在逻辑上应该是等价的。
工作正常:
char *src1; int esi_out, eax;
__asm__
__volatile__(
"lodsb\n\t;"
: "=&S" (esi_out), "=&a" (eax)
: "0" (src1)
);
printf("src1 %c @ %p, esi_out: %x, eax: %x\n", *src1, src1, esi_out, eax);
并打印:
src1 w @ 0x7fffce186959, esi_out: ce18695a, eax: ce186977
所以我的理解是这段代码应该将 src1 的值(这是一个地址)加载到 ESI 中,将该值复制到 EAX 中,将 ESI 中的地址增加 1 个字节,然后在退出时将这些值输出到本地C 变量 esi_out 和 eax。 src1 和 esi_out 看起来是正确的,但 eax 似乎已经关闭了。这是怎么回事?
第二段代码是我们看到一个我无法完全掌握的段错误:
__asm__
__volatile__(
"movl %%ebx, %%esi\n\t;"
//"lodsb\n\t;"
: "=&S" (esi_out), "=&b" (ebx), "=&a" (eax)
: "1" (src1)
);
printf("src1 %c @ %p, esi_out: %x, eax: %x, ebx: %x\n",
*src1, src1, esi_out, eax, ebx);
注释掉 lodsb 命令后,它会产生:
src1 w @ 0x7ffff093b959, esi_out: f093b959, eax: f093b959, ebx: f093b959
如果没有注释掉 lodsb 命令,它会出现段错误。以我的思路,直接加载ESI值,如上面第一种情况,加载到EBX,然后movl'ing到ESI应该是等价的吧?
我错过了什么?为什么写入 EAX 的值看起来不对?我将等效程序直接编写到汇编中,并使用 gdb 逐步执行它,它工作正常。
任何见解将不胜感激。
【问题讨论】:
-
这确实是一个关于使用 64 位指针但仅将低 32 位移动到寄存器中的问题。谢谢大家。