MinGW:与 -nostdlib 链接产生无效的可执行文件

MinGW: Linking with -nostdlib produces invalid executable

我花了最后几个小时尝试 link 一个简单的 x86 汇编程序,没有 任何 使用 MinGW 的 CRT 初始化代码。我希望 executable 只包含下面列出的 _main 方法和 ExitProcess 内核函数的单个导入。

在反汇编器中打开各种生成的文件显示 _main 确实是入口点并且导入 table 包含从 ExitProcess 导入(没有名称装饰) =16=],但是 Windows 不会加载 executable,声称“%1 不是有效的 Win32 应用程序。”

我注意到的一件奇怪的事情是,当我在 Resource Hacker 中打开文件时,添加一个小的嵌入式资源并保存,生成的文件执行时没有问题。这让我相信这不是 linking 步骤本身的问题,而是文件头的问题,因为这应该是该过程中唯一发生变化的部分。删除嵌入资源并再次保存会导致 Resource Hacker 崩溃并将 executable 恢复到之前的损坏状态。

代码

; test.asm
global _main
extern _ExitProcess@4
section .text
_main:
    push    0
    call    _ExitProcess@4

尝试失败

所有命令都成功执行,没有控制台输出。我还尝试将 -lkernel32-Wl,-e_main 的各种组合添加到 gcc 调用中,其中 none 似乎有任何效果。

环境

C:\Projects\asm>systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
OS Name:     Microsoft Windows 10 Home
OS Version:  10.0.19041 N/A Build 19041

C:\Projects\asm>nasm --version
NASM version 2.15.05 compiled on Aug 28 2020

C:\Projects\asm>gcc --version
gcc (MinGW.org GCC Build-2) 9.2.0

C:\Projects\asm>ld --version
GNU ld (GNU Binutils) 2.32

根据要求,我将post作为答案,但有一个重要的警告:

While this fixes the problem as posted, I don't really understand why. I'm not aware of (and can't find) any Windows PE requirement that you must have an rdata section, which suggests this is fixing things "by accident."

Also, while I'm using rdata here, pdata also works (but data does not).

考虑到这一点,您可以通过添加 rdata 部分来解决问题。所以按如下方式更改代码解决了问题,允许可执行文件按预期 运行:

; test.asm

section .rdata
db      9

section .text
extern _ExitProcess@4

global _main
_main:
    push    0
    call    _ExitProcess@4