assembly 为什么GCC链接器在Windows(x86-64 asm)上抛出错误?

k3bvogb1  于 2023-06-23  发布在  Windows
关注(0)|答案(1)|浏览(179)

我正在尝试编写x86-64程序集,以运行在当前的windows系统(在我的例子中,旧的windows 11)。我首先尝试了一个基于this post的基本程序:

; ----------------------------------------------------------------------------
; Hello_world.asm
;
; This is a Win64 console program that writes "Hello, World" on one line and
; then exits.  It needs to be linked with a C library.
; ----------------------------------------------------------------------------

    global  _main
    extern  printf

    section .text
_main:
    push    message
    call    printf
    add     esp, 4
    ret
message:
    db  'Hello, World', 10, 0

当我去组装和链接时,我得到以下错误:

nasm -fwin64 Hello_world.asm

gcc Hello_world.obj

错误:

Hello_world.obj:Hello_world.asm:(.text+0x1): relocation truncated to fit: IMAGE_REL_AMD64_ADDR32 against `.text'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../lib/libmingw32.a(lib64_libmingw32_a-crtexewin.o): in function `main':
C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexewin.c:70: undefined reference to `WinMain'
collect2.exe: error: ld returned 1 exit status

我该怎么解决?

x759pob2

x759pob21#

您编写的代码是32位的,但您正在为64位汇编和链接它。我将解释如何创建32位和64位应用程序。

在Windows上创建32位应用

您的代码几乎是正确的,但您还需要修饰printf(使其为_printf)。

global  _main
    extern  _printf

    section .text
_main:
    push    message
    call    _printf
    add     esp, 4
    ret
message:
    db  'Hello, World', 10, 0

汇编这段代码很容易:

nasm -f win32 Hello_world.asm

使用MinGW工具链链接它有点棘手,因为默认编译器仅为64位(如果使用-m32,您将获得数十个未定义的引用)。
幸运的是,它们提供了一组单独的32位工具here。如果你设法将它正确地安装到PATH变量中,你应该能够正常使用它,如下所示:

i686-w64-mingw32-gcc Hello_world.obj

在Windows上创建64位应用

在64位模式下,调用约定不同。在Windows中,使用Microsoft x64 calling convention。函数的前4个参数在RCXRDXR8R9寄存器中传递。这意味着我们的message应该放在RCX中。
您还需要分配32字节的堆栈空间(它们是为编译器设计的,以便它们将参数溢出到堆栈,但无论是否使用它们,它们总是需要存在)。
最后,ABI规定,当执行CALL指令时,堆栈需要对齐16个字节。因此,我们必须再分配8个字节用于对齐。总共40个。
还要注意,对于64位代码,名称不需要修饰。

global  main
    extern  printf

    section .text
main:
    sub     rsp, 40
    mov     rcx, message
    call    printf
    add     rsp, 40
    ret
message:
    db  'Hello, World', 10, 0

装配和连接:

nasm -f win64 Hello_world.asm
gcc Hello_world.obj

相关问题