有人可以解释一下这个NASM计划是如何运作的吗?

时间:2015-01-20 08:15:49

标签: assembly x86 nasm

这是我从Stackoverflow.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

好的,任何人都可以告诉这份副本espebp寄存器的内容,但是如何将未初始化的寄存器值复制到寄存器呢?它会加载ebp 0(零)吗?

SUB esp, 4

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

MOV ebx, eax

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

和最后一个,hlt

2 个答案:

答案 0 :(得分:2)

  1. esp永远不会“未初始化”。它始终指向堆栈的顶部 - 您推送和弹出的东西。例如,当您按下32位寄存器时,esp会自动减少4。

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

  3. 非常正确,从_GetStdHandle返回了eax。

  4. “hlt”停止处理器 - 这是一件坏事。但正如评论所说 - 因为_ExitProcess不会返回,所以不会被执行。想法可能是如果 _ExitProcess应该返回,最好暂停,而不是开始执行随机代码。

答案 1 :(得分:2)

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

mov ebp, esp

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

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

堆栈向下增长,例如:如果ESP在程序启动时由OS设置为0FFFF0000h,则EBP将设置为此值,减法将减少为0FFFEFFFCh,为本地4字节var @ this地址提供空间,

将在稍后引用
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