有人可以向我解释这个 NASM 程序是如何工作的吗?

Can Someone explain me how this NASM Program works?

这是我从 whosebug.com's Question:

复制的代码
global _main
    extern  _GetStdHandle@4
    extern  _WriteFile@20
    extern  _ExitProcess@4

    section .text
_main:
    ; DWORD  bytes;    
    mov     ebp, esp
    sub     esp, 4

    ; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
    push    -11
    call    _GetStdHandle@4
    mov     ebx, eax    

    ; WriteFile( hstdOut, message, length(message), &bytes, 0);
    push    0
    lea     eax, [ebp-4]
    push    eax
    push    (message_end - message)
    push    message
    push    ebx
    call    _WriteFile@20

    ; ExitProcess(0)
    push    0
    call    _ExitProcess@4

    ; never here
    hlt
message:
    db      'Hello, World', 10
message_end:

此代码工作正常,无需清除任何错误,但有些行我无法理解它们的作用,向下滚动:

MOV ebp, esp

好吧,任何人都可以告诉这将 esp 的内容复制到 ebp 寄存器,但是这怎么可能将未初始化的寄存器的值复制到寄存器?它会用 0(零)加载 ebp 吗?

SUB esp, 4

这里esp4减去,所以0-4= -4,不是吗?但是为什么是这两行代码呢?相反,如果结果是我给出的结果 "-4" 我会让 Normaly 做 MOV esp, -4

MOV ebx, eax

还有eax,我认为它必须由_GetstdHandle函数填充?

最后一个,hlt?

  1. esp 永远不会是 "uninitialized"。它总是指向堆栈的顶部——你推入和弹出东西的地方。比如压入一个32位的寄存器,esp自动减四

  2. "sub esp, 4" 在堆栈上分配四个字节 - 用于 "bytes" 变量。后面可以看到"lea ax, [ebp-4]",对应注释中的“&bytes”

  3. 完全正确,eax return来自 _GetStdHandle。

  4. "hlt" 停止处理器 - 一件坏事。但正如评论所说 - 不会被执行,因为 _ExitProcess 不会 return。这个想法可能是 if _ExitProcess 应该 return,暂停比开始执行随机代码更好。

总结一下,这个程序用一个局部变量创建了一个堆栈帧,然后从上面的 'extern' 导入的 kernel32.lib 调用 Win32 API 函数,并以 SUCCESS (0) 退出。

mov ebp, esp

将基指针寄存器设置为 SS:ESP 的当前值。这样做是为了访问用

保留的本地 DWORD 变量(4 字节)
sub esp, 4

堆栈向下增长,例如:如果 ESP 是程序启动时由 OS 设置的 0FFFF0000h,则 EBP 将设置为此值并且减法会将其减少到 0FFFEFFFCh 给出 space对于local 4 byte var @this address,后面会引用到

lea     eax, [ebp-4]      ; &bytes

mov ebx, eax

将句柄保存在 EBX 中的 EAX 中(在这种情况下不需要),因为

Registers EBP, EBX, ESI, and EDI are preserved during Win32 API calls.

末尾的 HLT 是无法访问的代码,因此永远不应执行。无论如何,它会停止进一步执行,请看这里:http://www.felixcloutier.com/x86/HLT.html