Winapi 如果我正在使用Win32入口点,我是否应该增加esp值以从堆栈中删除变量?

Winapi 如果我正在使用Win32入口点,我是否应该增加esp值以从堆栈中删除变量?,winapi,assembly,x86,nasm,Winapi,Assembly,X86,Nasm,如果我正在使用Win32入口点,并且我有以下代码(在NASM中): 现在,在退出进程之前,我是否应该增加esp值,以便像处理任何“正常”函数一样从堆栈中删除这两个变量?ExitProcessapi可以从任何位置调用。在任何函数和子函数中。当然,堆栈指针可以是任意的。您不需要将任何寄存器(包括堆栈指针)设置为某些(和哪些?)值。所以回答-你不需要增加esp 如上所述@HarryJohnston当然堆栈必须有效且对齐。在任何api调用之前exiproces是常用的api。并且可以作为任何其他api

如果我正在使用Win32入口点,并且我有以下代码(在NASM中):


现在,在退出进程之前,我是否应该增加
esp
值,以便像处理任何“正常”函数一样从堆栈中删除这两个变量?

ExitProcess
api可以从任何位置调用。在任何函数和子函数中。当然,堆栈指针可以是任意的。您不需要将任何寄存器(包括堆栈指针)设置为某些(和哪些?)值。所以回答-你不需要增加esp


如上所述@HarryJohnston当然堆栈必须有效且对齐。在任何api调用之前<代码>exiproces是常用的api。并且可以作为任何其他api调用。和其他任何api一样,它只需要有效的堆栈,而不需要具体的堆栈指针值。非易失性寄存器只需还原即可返回调用方。但是
ExiProcess
不会返回调用方。它再也不会回来了


所以,规则非常简单——若您从任何函数返回(入口点或绝对任意值——无所谓)——我们需要恢复非易失性寄存器(基于调用约定的堆栈指针esp或rsp)并返回。如果我们不返回调用者-我们不需要恢复/保留任何寄存器。如果我们从线程或进程入口点返回,尽管有很好的实践,但在当前的windows实现中也恢复了所有寄存器,即使我们不这样做,任何方式都可以,因为内核32 shell调用程序在返回后只需调用
ExitThread
。这里不使用任何非易失性寄存器或局部变量。因此,即使不从入口点还原,代码也可以工作,但无论如何还原它要好得多

ExitProcess
api可以从任何地方调用。在任何函数和子函数中。当然,堆栈指针可以是任意的。您不需要将任何寄存器(包括堆栈指针)设置为某些(和哪些?)值。所以回答-你不需要增加esp


如上所述@HarryJohnston当然堆栈必须有效且对齐。在任何api调用之前<代码>exiproces是常用的api。并且可以作为任何其他api调用。和其他任何api一样,它只需要有效的堆栈,而不需要具体的堆栈指针值。非易失性寄存器只需还原即可返回调用方。但是
ExiProcess
不会返回调用方。它再也不会回来了


所以,规则非常简单——若您从任何函数返回(入口点或绝对任意值——无所谓)——我们需要恢复非易失性寄存器(基于调用约定的堆栈指针esp或rsp)并返回。如果我们不返回调用者-我们不需要恢复/保留任何寄存器。如果我们从线程或进程入口点返回,尽管有很好的实践,但在当前的windows实现中也恢复了所有寄存器,即使我们不这样做,任何方式都可以,因为内核32 shell调用程序在返回后只需调用
ExitThread
。这里不使用任何非易失性寄存器或局部变量。因此,即使没有从入口点还原,代码也可以工作,但无论如何还原它要好得多

这与我读到的上一个问题本质上不一样吗?如果你理解上一个问题的答案,那么你可以在这里应用这些知识,不?编写
sub esp,4
两次总是比
sub esp更糟糕,8
。在汇编语言中,没有编译器为您优化冗余。您正在调用一个
\u Noreturn
函数,而不是返回。所以,就像任何其他函数调用一样,不,在进行另一个调用之前,您不需要做任何事情。Johan的回答是关于从应用程序的main()函数返回的问题,或者至少Johan是这样解释的。与您的情况完全不同,您正在使用Win32入口点,但无论如何都不会从中返回。这与我读到的上一个问题本质上不一样吗?如果您理解上一个问题的答案,那么您可以在这里应用这些知识,不是吗?编写
sub esp,4
两次总是比
sub esp更糟糕,8
。在汇编语言中,没有编译器为您优化冗余。您正在调用一个
\u Noreturn
函数,而不是返回。所以,就像任何其他函数调用一样,不,在进行另一个调用之前,您不需要做任何事情。Johan的回答是关于从应用程序的main()函数返回的问题,或者至少Johan是这样解释的。与您的情况完全不同,您使用的是Win32入口点,而不是从它返回。+1。不过,为了明确起见,当您调用
ExitProcess
时,堆栈指针必须有效,也就是说,它必须正确对齐(如果适用)并指向堆栈分配中的某个位置。例如,如果它被设置为零,程序将崩溃,而不是干净地退出。但你在堆栈中的位置并不重要。无论你从哪个线程调用它都无关紧要@HarryJohnston-当然,堆栈必须有效且对齐。我只是假设它是默认的。我想说的是OP-the
ExiProcess
是一个常用的api。并且可以作为任何其他api调用。和其他api一样,它只需要有效的堆栈,而不需要具体的值。非易失性寄存器只需在返回给调用者时恢复。但是
ExiProcess
不会返回调用方。这根本就不可能return@Harry约翰斯顿:如果你不介意的话,我有两个问题:1)“堆栈指针必须是有效的,也就是说,它必须正确对齐”你说的“正确对齐”是什么意思,你是说
esp
必须对齐4个字节,并且当我只调用
ExitProcess()时它必须对齐吗
或者当我调用任何函数时?2) 并指向堆栈分配中的某个地方“stack al”是什么意思
extern _ExitProcess@4

global _start

section .text
_start:
    mov ebp, esp

    ; Reserve space onto the stack for two 4 bytes variables
    sub esp, 4
    sub esp, 4

    ; ExitProcess(0)
    push 0
    call _ExitProcess@4