编译器为什么会左移0?

12

我写完这个简单程序后,在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  
...

10
你是否开启了优化? - Jester
似乎只为x86添加了shift,而不是x64。同时在发布版本中似乎会消失。 - wally
1个回答

11

请注意,这是在评估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

* 在这种特定情况下,即使在编译时不知道N,也不需要使用shl[ecx + eax * 4]可以通过单个指令访问。这将是另一种通常执行的优化。


我认为MSVC在前端执行强度降低,这是有道理的,因为它基于pcc(如果我没记错的话,它也这样做)。 - fuz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接