在我编写这个简单的程序之后,当我在Visual Studio中进入反汇编模式时,我注意到了一些奇怪的事情:编译器添加了一个向左移位0位的指令。
为什么这样做?
这是C ++代码:
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
if (argc != 3)
return 0;
if (strcmp(argv[1], "-r") == 0) {
printf("test");
}
return 0;
}
这是汇编代码:
...
return 0;
00131C94 xor eax,eax
00131C96 jmp main+57h (0131CC7h)
if (strcmp(argv[1], "-r") == 0) {
00131C98 push offset string "-r" (0138B30h)
00131C9D mov eax,4
00131CA2 shl eax,0 <------------------------- HERE
00131CA5 mov ecx,dword ptr [argv]
00131CA8 mov edx,dword ptr [ecx+eax]
00131CAB push edx
00131CAC call _strcmp (01313D9h)
00131CB1 add esp,8
00131CB4 test eax,eax
00131CB6 jne main+55h (0131CC5h)
printf("test");
00131CB8 push offset string "test" (0138BD0h)
00131CBD call _printf (01313E8h)
00131CC2 add esp,4
...
答案 0 :(得分:12)
请注意,这用于评估argv[1]
。
通常,argv[N]
需要由编译器转换为*((char**) ((char*) argv + N * sizeof *argv))
:每个指针在下一个之后是sizeof *argv
个字节。如果在编译时不知道N
,则乘法需要在那里,shl
是正常的做法。 *
由于N
在编译时已知,但您尚未启用优化,我会猜到这会编译为
00131C9D mov eax,1
00131CA2 shl eax,2
显然,即使禁用了优化,Visual Studio也可以将其简化为您所看到的内容,但如果没有优化,它仍然无法完全摆脱shl
。 / p>
* 在这种特定情况下,即使在编译时不知道shl
,也不需要N
:{{1}可以使用单个指令访问。这将是通常会执行的另一项优化。