可执行程序与64位处理器不兼容

时间:2015-08-23 21:03:30

标签: windows assembly console-application nasm

我的问题是:当我尝试执行在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

1 个答案:

答案 0 :(得分:0)

你以这种方式运行汇编程序:

nasm -fwin32 main.asm -o main.exe

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

所以你应该以这种方式执行nasm:

nasm -fwin32 main.asm -o main.obj

这会输出文件main.obj。您无法运行目标文件。它必须由链接器处理才能生成exe。链接器还将用于解析系统调用,如WriteConsoleAExitProcess等。

有许多链接器,包括名为 link.exe 的Microsoft的链接器。我不知道你是否安装了Microsoft编译器,所以我建议你使用免费的编译器来帮助你。您可以从here下载名为GoLink的一个。您可以阅读GoLink手册here。下载后,您可以将 GoLink.exe 提取到与 nasm.exe 相同的目录。

您需要用来将main.objmain.exe关联起来的命令是:

GoLink.exe main.obj kernel32.dll /fo main.exe /console

这将main.objkernel32.dll并将它们链接在一起并生成一个名为main.exe的可执行文件。 kernel32.dll是包含系统函数WriteConsoleAExitProcessReadConsoleInputAGetStdHandle的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]   指向接收输入记录数的变量的指针   读取。