这条指令是什么意思?


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 

与(从IDA输出)的箭头标记线示出了两个MOV操作哪个语义等于无(或是什么?)。这是我的源代码:

#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 

更新:我试过其他选项,两者/ O1和/ O2不具有这样的结构,但/ Ot具有相同的指令对。当我编译它与/ Os有:

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

谢谢。

  0

如果您在调试模式下编译,compilrr通常会保存返回值,所以它将eax保存到dwird pid中,然后使用保存的pid作为printf 26 11月. 172017-11-26 03:12:30

  0

您的意思是Visual Studio的调试模式?我检查了Visual Studio模式。实际上,调试模式具有相同的配对,但在代码和调试结构方面存在很多其他差​​异。在释放模式下,在IsDebuggerPresent之前有一个nop,我不知道它是否相关。 26 11月. 172017-11-26 08:32:34

  0

@ de6f发布模式涉及很多优化的朴素代码,这就是为什么长度有所不同。 27 11月. 172017-11-27 13:25:19

  0

了解,但为什么编译器首先生成该代码?有什么其他的好处呢? 27 11月. 172017-11-27 16:31:26

+1

@de6f你有一个statemeny pid = blah编译器在堆栈ebp-xx中分配了一个本地var pid并存储了blah的结果然后你有一个printf编译器然后重用本地它不记住结果是在eax已经它在调试模式编译时告诉它优化它时,它会告诉它在调试模式下消除该对,这对可以帮助源代码级调试 27 11月. 172017-11-27 17:58:31

  0

如果在正常编译过程中没有记住它,这似乎更合理。 27 11月. 172017-11-27 21:36:58

1

该代码使用此非最佳形式来匹配原始代码。它将值保存在本地“pid”变量中,以便调试器可以看到它。然后它再次获取该值以便使用它。