2017-03-19 22 views
13

Po napisaniu tego prostego programu, kiedy poszedłem do trybu demontażu w Visual Studio zauważyłem coś dziwnego: kompilator dodał instrukcję przesunięcia w lewo o 0 bitów.Dlaczego przesunięcie kompilatora w lewo o 0?

Dlaczego to robi?

Jest to kod 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; 
} 

Jest to kod montaż:

... 
     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

Czy włączono optymalizacje? – Jester

+0

Wydaje się, że dodaje tylko przesunięcie dla x86, a nie x64. Wydaje się również zanikać w przypadku wydania wersji. – wally

Odpowiedz

12

Należy zauważyć, że jest to stosowane w ocenie argv[1].

Ogólnie rzecz biorąc, argv[N] musi być przetłumaczone przez kompilator na *((char**) ((char*) argv + N * sizeof *argv)): każdy wskaźnik to sizeof *argv bajtów po następnym. Kiedy N nie jest znany podczas kompilacji, musi się tam pojawić mnożenie, a shl jest to normalny sposób. *

Od N jest znany w czasie kompilacji, ale nie zostały włączone optymalizacje, bym domyślić byłoby skompilować do

00131C9D mov   eax,1 
00131CA2 shl   eax,2 

Widocznie Visual Studio jest w stanie uprościć to do tego, co "Widzimy, nawet gdy optymalizacje są wyłączone, ale bez optymalizacji, nadal nie jest w stanie całkowicie pozbyć się shl.

* W tym konkretnym przypadku, shl nie byłyby potrzebne, nawet jeśli N nie jest znany w czasie kompilacji: [ecx+eax*4] można uzyskać z jednej instrukcji. To byłaby kolejna optymalizacja, która normalnie byłaby wykonywana.

+0

Przypuszczam, że MSVC dokonuje redukcji siły w interfejsie, co ma sens, ponieważ jest oparty na PCC (co również robi to w IIRC). – fuz

Powiązane problemy