这个问题在这里已经有了答案:
9年前关闭。
Possible Duplicate:
What's the point of LEA EAX, [EAX]?
在一次反汇编练习中,我观察到以下代码:
测试.cpp:
#include <stdio.h>
int main(int argc, char * argv[]) {
for (int i = 0; i < 10 ; ++i) {
printf("%i\n", i);
}
int i = 0;
while ( i < 10) {
printf("%i\n", i);
++i;
}
return 0;
}
使用 vc++ 2008 编译并优化:
cl /Ox test.cpp
main函数拆解:
.text:00401000 var_4 = dword ptr -4 ; BTW, IDA fails to see that esi is pushed to save it, not to allocate space to local variable
.text:00401000
.text:00401000 push esi
.text:00401001 xor esi, esi
.text:00401003
.text:00401003 loc_401003: ; CODE XREF: sub_401000+15j
.text:00401003 push esi
.text:00401004 push offset byte_40A150
.text:00401009 call sub_401038 ; printf
.text:0040100E inc esi
.text:0040100F add esp, 8
.text:00401012 cmp esi, 0Ah
.text:00401015 jl short loc_401003
.text:00401017 xor esi, esi
.text:00401019 lea esp, [esp+0]
.text:00401020
.text:00401020 loc_401020: ; CODE XREF: sub_401000+32j
.text:00401020 push esi
.text:00401021 push offset unk_40A154
.text:00401026 call sub_401038 ; printf
.text:0040102B inc esi
.text:0040102C add esp, 8
.text:0040102F cmp esi, 0Ah
.text:00401032 jl short loc_401020
.text:00401034 xor eax, eax
.text:00401036 pop esi
.text:00401037 retn
现在,正如您从示例代码中看到的那样,我并不完全是专家,但是考虑到我编写了原始代码,我能够弄清楚这个程序集列表。唯一困扰我的是以下行:
.text:00401019 lea esp, [esp+0]
编译器为什么要这样做?它不会影响任何寄存器或标志,而且它似乎是一个冗余代码。我唯一能想到的是,编译器将 jmp 在第二个循环(loc_401020)中转到的代码对齐,这可能是原因吗?
最佳答案
是的,看起来它正在插入填充以对齐跳转目标。如果您使用 /Fa
让编译器产生汇编输出,显示为 npad 7
,明确表示它正在插入填充。从那里开始,由汇编程序挑选出它可以找到的最有效的指令序列来使用指定的空间,同时使用尽可能少的 CPU 时间。
关于visual-c++ - 编译代码中的冗余指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7987622/