【问题标题】:Executable isn't compatible with 64 bits processor可执行文件与 64 位处理器不兼容
【发布时间】:2015-08-23 21:03:29
【问题描述】:

我的问题是:当我尝试执行在 NASM 和 Windows 8 64 位中组装的 .exe 时,告诉我这个 .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

【问题讨论】:

  • 您生成的是 Microsoft Win32 对象文件。您必须使用链接器从该目标文件生成可执行文件。

标签: windows assembly console-application nasm


【解决方案1】:

你是这样运行汇编程序的:

nasm -fwin32 main.asm -o main.exe

如果您使用-fwin32 进行汇编,这将不会生成可执行文件。它实际上生成了一个目标文件。问题是在这种情况下OBJ 文件不是可执行文件。这就像获取一个TXT 文件,将其重命名为EXE 并尝试运行它。不会的。

所以你应该这样执行 nasm:

nasm -fwin32 main.asm -o main.obj

这会输出一个文件main.obj。您不能运行目标文件。它必须由链接器处理以生成exe。链接器还将用于解析WriteConsoleA、ExitProcess 等系统调用。

有许多链接器,包括 Microsoft 的链接器 link.exe。我不知道您是否安装了 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 变量(使用resd 分配的单个DWORD 到.bss 部分):

    events_read         resd 1

您可以找到ReadConsoleInputAhere 的 Microsoft 文档以了解有关参数的更多信息。请注意,对于 32 位 Windows 应用程序,参数会以文档中出现的相反顺序推送到堆栈中。文档说:

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] 指向接收输入记录数的变量的指针 阅读。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-26
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    相关资源
    最近更新 更多