【问题标题】:Why does the compiler shift left by 0?为什么编译器左移0?
【发布时间】:2017-03-19 12:02:19
【问题描述】:

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

【问题讨论】:

  • 你启用优化了吗?
  • 似乎只为 x86 添加了移位,而不是 x64。 Release 版本似乎也消失了。

标签: c++ assembly visual-c++


【解决方案1】:

请注意,这是在评估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(IIRC 也这样做)。
猜你喜欢
  • 2015-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-26
  • 2018-03-21
  • 1970-01-01
  • 2018-05-22
  • 1970-01-01
相关资源
最近更新 更多