这个指令对是什么意思?

逆向工程 拆卸 编译器
2021-07-11 23:00:08

我不知道是否有人问过它,但是尽管有这个问题,我还是找不到任何东西是因为拆机的错吗?或者如果它是对的,为什么编译器会生成这段代码?

 ; 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_

谢谢。

1个回答

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