【发布时间】:2019-08-27 06:12:34
【问题描述】:
我正在使用一台AMD64计算机(Intel Pentium Gold 4415U)来比较一些从C语言转换而来的汇编指令(当然,确切地说,是反汇编)。
在 Windows 10 中,我将 Visual Studio 2017(15.2) 与他们的 C 编译器一起使用。 我的示例代码如下所示:
int main() {
int i = 0;
if(++i == 4);
if(i++ == 4);
return 0;
}
反汇编如下:
mov eax,dword ptr [i] // if (++i == 4);
inc eax
mov dword ptr [i],eax
mov eax,dword ptr [i] // if (i++ == 4);
mov dword ptr [rbp+0D4h],eax ; save old i to a temporary
mov eax,dword ptr [i]
inc eax
mov dword ptr [i],eax
cmp dword ptr [rbp+0D4h],4 ; compare with previous i
jne main+51h (07FF7DDBF3601h)
mov dword ptr [rbp+0D8h],1
jmp main+5Bh (07FF7DDBF360Bh)
*mov dword ptr [rbp+0D8h],0
07FF7DDBF3601 转到最后一行指令(*)。
07FF7DDBF360B 去'return 0;'。
在if (++i == 4) 中,程序不会观察“添加”i 是否满足条件。
但是在if (i++ == 4) 中,程序将“前一个”i 保存到堆栈中,然后进行增量。之后,程序将“前一个”i 与常数整数 4 进行比较。
两个C代码不同的原因是什么?它只是编译器的机制吗?更复杂的代码会有所不同吗?
我试图通过 Google 找到有关此问题的信息,但未能找到差异的根源。我必须了解“这只是编译器行为”吗?
【问题讨论】:
-
闻起来像优化。
-
代码相当于
return 0;编译器可以优化掉其他任何东西。 -
@PaulOgilvie:除了它没有优化。这显然是未经优化的编译器输出,它单独编译每个 C 语句,不进行任何常量传播,并且有效地将所有本地变量视为
volatile,因此如果调试器修改它们,程序仍然可以工作。当然,它仍然可以在in语句中进行优化,并在空的ifbody 上移除跳转。 -
为什么要查看调试模式程序集?您想从中获得什么见解?
-
不太清楚他的意思。当然它们的工作方式不同,这就是为什么有两个操作的原因。我们不需要两个工作相同的操作,现在是吗?
标签: c assembly visual-c++ reverse-engineering