Что означают эти пары команд?


1

Не знаю, если это задано, но я не мог найти ничего, несмотря на вопрос this. Это из-за ошибки дизассемблера? Или, если это правильно, почему компилятор генерирует этот код?

; int __cdecl main(int argc, const char **argv, const char **envp) 
main   proc near    ; CODE XREF: start-7Bp 

var_4   = dword ptr -4 
argc   = dword ptr 8 
argv   = dword ptr 0Ch 
envp   = dword ptr 10h 

       push ebp 
       mov  ebp, esp 
       push ecx 
       call ds:GetCurrentProcessId 
       mov  [ebp+var_4], eax ; <--- 
       mov  eax, [ebp+var_4] ; <--- 
       push eax 
       push offset output 
       call printf 
       add  esp, 8 

debugger_wait:       ; CODE XREF: main+28j 
       call ds:IsDebuggerPresent 
       test eax, eax 
       jnz  short debugger_present 
       jmp  short debugger_wait 
; --------------------------------------------------------------------------- 

debugger_present:      ; CODE XREF: main+26j 
       int  3    ; Trap to Debugger 
       xor  eax, eax 
       mov  esp, ebp 
       pop  ebp 
       retn 
main   endp 

Отмеченные линии со стрелками (от выхода МАР) показывает два МОВ операции, которые семантически равно ничего (или это?). Это мой исходный код:

#include <stdio.h> 
#include <Windows.h> 

int main(int argc, char *argv[], char *envp[]) 
{ 
    DWORD pid = GetCurrentProcessId(); 
    printf("%d\n", pid); 
    while (!IsDebuggerPresent()); 
    __asm int 0x3; 
    return 0; 
} 

Собран с MSVC++ (19.00.24225.1):

cl.exe dnmProg.c 

UPDATE: Я попробовал другие варианты, и как/O1 и/O2 не имеют такую ​​структуру, но/Ot имеет ту же пару команд. Когда я скомпилировал его с/Os, есть:

call ds:GetCurrentProcessId 
mov  [ebp+var_4], eax ; <--- 
push [ebp+var_4]  ; <--- 
push offset printf_parameter 
call printf_ 

Спасибо.

  0

Если вы компилируете в режиме отладки, то компилятор обычно сохраняет возвращаемые значения i, чтобы сохранить eax в dwird pid, а затем использовать сохраненный pid для printf. 26 ноя. 172017-11-26 03:12:30

  0

Вы имеете в виду режим отладки Visual Studio? Я изучил режимы Visual Studio. Действительно, режим отладки имеет одну и ту же пару, но с большим количеством других различий в структуре кода и отладки. В режиме выпуска есть nop перед IsDebuggerPresent, который я не знаю, связано ли это или нет. 26 ноя. 172017-11-26 08:32:34

  0

@ Режим деблокирования de6f включает в себя много оптимизаций наивного кода, поэтому существует разница в длине. 27 ноя. 172017-11-27 13:25:19

  0

Поймите это, но почему компилятор генерирует этот код на первом месте? Любое другое преимущество для этого? 27 ноя. 172017-11-27 16:31:26

+1

@ de6f у вас есть statemeny pid = компилятор blah назначил локальный var pid в стеке ebp-xx и сохранил результат blah там, тогда у вас есть printf компилятор, а затем повторно используется локальный, он не имеет в виду, что результат уже в eax уже он делает так, как сказано, когда в режиме отладки компиляции, когда вы говорите, чтобы оптимизировать его, он устраняет пару в режиме отладки. Пара помогает отладке исходного уровня. 27 ноя. 172017-11-27 17:58:31

  0

Кажется более разумным, если это не учитывать это при обычном процессе компиляции. 27 ноя. 172017-11-27 21:36:58

1

Код использует эту неоптимальную форму для соответствия исходному коду. Он сохраняет значение в локальной переменной «pid», чтобы отладчик мог ее видеть. Затем он снова извлекает значение для его использования.