有人可以向我解释这个 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
这里esp
被4
减去,所以0-4= -4
,不是吗?但是为什么是这两行代码呢?相反,如果结果是我给出的结果 "-4"
我会让 Normaly 做 MOV esp, -4
MOV ebx, eax
还有eax
,我认为它必须由_GetstdHandle
函数填充?
最后一个,hlt
?
esp 永远不会是 "uninitialized"。它总是指向堆栈的顶部——你推入和弹出东西的地方。比如压入一个32位的寄存器,esp自动减四
"sub esp, 4" 在堆栈上分配四个字节 - 用于 "bytes" 变量。后面可以看到"lea ax, [ebp-4]",对应注释中的“&bytes”
完全正确,eax return来自 _GetStdHandle。
"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
这是我从 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
这里esp
被4
减去,所以0-4= -4
,不是吗?但是为什么是这两行代码呢?相反,如果结果是我给出的结果 "-4"
我会让 Normaly 做 MOV esp, -4
MOV ebx, eax
还有eax
,我认为它必须由_GetstdHandle
函数填充?
最后一个,hlt
?
esp 永远不会是 "uninitialized"。它总是指向堆栈的顶部——你推入和弹出东西的地方。比如压入一个32位的寄存器,esp自动减四
"sub esp, 4" 在堆栈上分配四个字节 - 用于 "bytes" 变量。后面可以看到"lea ax, [ebp-4]",对应注释中的“&bytes”
完全正确,eax return来自 _GetStdHandle。
"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