我的问题是:当我尝试执行在NASM和Windows 8中组装的.exe时,64位告诉我这个.exe与64位不兼容。那么,我该如何组装这段代码(我是从网上获得的)?
使用过的代码
STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
NULL equ 0
global start
extern ExitProcess, GetStdHandle, WriteConsoleA, ReadConsoleInputA
section .data ;message we want to display on console
msg db "Press a key to continue...", 13, 10, 0
msg.len equ $ - msg
consoleInHandle dd 1
section .bss ;buffers declaration
buffer_out resd 2
buffer_in resb 32
section .text
start: ;starting point of our program
push STD_OUTPUT_HANDLE
call GetStdHandle ;call to get a handle to the
push NULL ;specified mode (input, output...)
push buffer_out
push msg.len
push msg
push eax ;contains the GetStdHandle result
call WriteConsoleA ;call to print our msg in console
read:
push STD_INPUT_HANDLE
call GetStdHandle ;new call to get input handle
push NULL
push 1
push buffer_in
push eax
call ReadConsoleInputA ;call to detect user input
;this function will wait til
exit: ;it detects enough keypresses
push NULL ;(in this case, 1)
call ExitProcess
用于组装此命令的命令: nasm -fwin32 main.asm -o main.exe
答案 0 :(得分:0)
你以这种方式运行汇编程序:
nasm -fwin32 main.asm -o main.exe
如果使用-fwin32
汇编,则不会生成可执行文件。它实际上生成了一个目标文件。问题是这种情况下的OBJ
文件不是可执行文件。这就像拿一个TXT
文件,将其重命名为EXE
并试图运行它。它没有赢。
所以你应该以这种方式执行nasm:
nasm -fwin32 main.asm -o main.obj
这会输出文件main.obj
。您无法运行目标文件。它必须由链接器处理才能生成exe
。链接器还将用于解析系统调用,如WriteConsoleA
,ExitProcess
等。
有许多链接器,包括名为 link.exe 的Microsoft的链接器。我不知道你是否安装了Microsoft编译器,所以我建议你使用免费的编译器来帮助你。您可以从here下载名为GoLink的一个。您可以阅读GoLink手册here。下载后,您可以将 GoLink.exe 提取到与 nasm.exe 相同的目录。
您需要用来将main.obj
与main.exe
关联起来的命令是:
GoLink.exe main.obj kernel32.dll /fo main.exe /console
这将main.obj
和kernel32.dll
并将它们链接在一起并生成一个名为main.exe
的可执行文件。 kernel32.dll
是包含系统函数WriteConsoleA
,ExitProcess
,ReadConsoleInputA
和GetStdHandle
的DLL(共享库)。如果没有它,链接器将无法创建最终的可执行文件,并将以错误说明退出。
您的程序中存在一个主要问题,即输入字符时可能会导致崩溃。我修改它看起来像这样:
STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
NULL equ 0
global start
extern ExitProcess, GetStdHandle, WriteConsoleA, ReadConsoleInputA
section .data ;message we want to display on console
msg db "Press a key to continue...", 13, 10, 0
msg.len equ $ - msg
section .bss ;buffers declaration
buffer_out resd 1
buffer_in resb 32
events_read resd 1
section .text
start: ;starting point of our program
push STD_OUTPUT_HANDLE
call GetStdHandle ;call to get a handle to the
push NULL ;specified mode (input, output...)
push buffer_out
push msg.len
push msg
push eax ;contains the GetStdHandle result
call WriteConsoleA ;call to print our msg in console
read:
push STD_INPUT_HANDLE
call GetStdHandle ;new call to get input handle
push events_read ;push dword buffer to return # of events read
;This paramater can't be NULL/0
push 1
push buffer_in
push eax
call ReadConsoleInputA ;call to detect user input
;this function will wait til
exit: ;it detects enough keypresses
push NULL ;(in this case, 1)
call ExitProcess
您的代码最初有:
push NULL
我把它改为:
push events_read ;push dword buffer to return # of events read
;This paramater can't be NULL/0
我还将events_read
变量(一个 DWORD 分配了resd
添加到.bss
部分):
events_read resd 1
您可以找到ReadConsoleInputA
here的Microsoft文档,以了解有关参数的更多信息。请注意,对于32位窗口,应用程序参数将按照文档中显示的相反顺序压入堆栈。文档说:
BOOL WINAPI ReadConsoleInput( _In_ HANDLE hConsoleInput, _Out_ PINPUT_RECORD lpBuffer, _In_ DWORD nLength, _Out_ LPDWORD lpNumberOfEventsRead );
参数
hConsoleInput [in]控制台输入缓冲区的句柄。手柄 必须具有GENERIC_READ访问权限。有关更多信息,请参阅 控制台缓冲区安全和访问权限。
lpBuffer [out]指向的指针 接收输入缓冲区的INPUT_RECORD结构数组 数据。此缓冲区的存储空间是从共享堆中分配的 进程大小为64 KB。缓冲区的最大大小 取决于堆的使用情况。
nLength [in]指向的数组大小 数组元素中的lpBuffer参数。
lpNumberOfEventsRead [out] 指向接收输入记录数的变量的指针 读取。