0

我为 win64 编写了一个 helloworld 程序,并使用 nasm 将其转换为 .obj 文件...现在我必须使用 alink 加载生成的 hello.obj 文件,但错误正在裁剪...

组装我使用了命令

   nasm -f win64 -o hello.obj helloworld.asm  

(这执行成功)

并加载我正在写

alink hello.obj 

但不断显示的错误是

loading file hello.obj 
unknown file type

然后一旦我写了 -f win32 而不是 -f win64... 然后当我为 alink 执行相同的加载代码(即 alink hello.obj)时,屏幕上写道

loading file hello.obj 
matched externs
matched comdefs
warning,no entry point specified
warning-no stack
error:target address out of frame
base=00000010, target=00000000

helloworld.asm 文件在这里

4

2 回答 2

2

您在使用 alink 时遇到的主要问题是它没有任何 64 位支持,这就是为什么您必须使用它nasm -fwin32来生成 32 位目标代码的原因。第二个问题是您没有指定入口点。令人沮丧,不是吗?我自己在不同的链接器上浪费了很多时间。

如果你想用 nasm 做 win64 汇编,我建议使用golink。它采用轻便、快速、严肃的方法进行链接。如果您想在代码中使用 DLL 中的函数,则不需要任何库文件——GoLink 可以仅使用 DLL 文件本身完成所有链接。它甚至会将它们从系统路径中拉出,因此您无需将任何内容放在与源代码相同的文件夹中。

您遇到的下一个主要问题是您的示例代码不适合 Windows。这是您可以开始使用的一个,当您运行它时不会崩溃:

; example64.s
; nasm -fwin64 example64.s
; golink /console example64.obj kernel32.dll msvcrt.dll

    bits 64
    default rel

    extern  GetStdHandle
    extern  WriteFile
    extern  ExitProcess
    extern  printf

section .data 
message db  'Hello, World!',10,0
msglen equ $-message
written dq      1

section .text
    global Start ; GoLink will use Start as the default entry point
Start:
    ; Use the C library to print our message
    mov rcx, message
    call    printf

    ; Now try using the Windows API
    mov rcx, -11
    call    GetStdHandle

    ; Use WriteFile to print our message again.
    ; Notice the calling convention for 64-bit Windows uses
    ; rcx, rdx, r8, and r9 for the first 4 non-floating point arguments
    ; and then the rest are pushed onto the stack.
    mov rcx, rax    ; HANDLE hFile
    mov rdx, message    ; LPCVOID lpBuffer
    mov r8, msglen  ; DWORD nNumberOfBytesToWrite
    mov r9, written ; LPDWORD lpNumberOfBytesWritten
    push    qword 0     ; LPOVERLAPPED lpOverlapped
    call    WriteFile

    mov rcx, 0
    call    ExitProcess

假设它保存为 example64.s,您可以像这样组装和链接它:

nasm -fwin64 example64.s

golink /console example64.obj kernel32.dll msvcrt.dll

请注意,我们包含 kernel32.dll 的原因是用于 Windows API 调用(WriteFile、ExitProcess、GetStdHandle)。同样,msvcrt.dll 用于标准 C 库函数(即 printf、malloc 等)。如果您想真正了解 Win64 程序集,您可能希望继续使用 Windows API,而忽略 msvcrt.dll。您可以在 MSDN 上找到所有 Windows API 函数和数据结构的文档。

最后,值得注意的是,他们在 MSDN 上提供的许多函数原型和结构都是针对 32 位 Windows API 的,因此每当您看到 DWORD 时,您可能会想要使用 QWORD 代替。

无论如何,我希望这能让你朝着你想去的方向开始。祝你好运!

于 2011-09-08T22:17:29.033 回答
0

如果你仍然想使用 ALINK,你可以试试这个:

  • 组装一个win32程序(用32b代码编写!):

    nasm -f obj file_name.asm
    
  • 组装一个win64程序(用64b代码编写!):

    nasm -f win64 file_name.asm
    

现在,32b 对象的链接过程:

alink -oPE -subsys con -entry Start file_name.obj

其中 Start 是您的程序的入口点,即您声明为全局的入口点。

对于 64b 对象,请按照 James 的建议尝试另一个链接编辑器,例如 goLink。

这应该这样做。希望它也适合你!

于 2011-12-15T11:49:49.817 回答