【发布时间】:2021-01-31 12:43:43
【问题描述】:
在过去的几个小时里,我尝试使用 MinGW 链接一个没有任何 CRT 初始化代码的简单 x86 汇编程序。我希望可执行文件只包含下面列出的_main 方法和ExitProcess 内核函数的单个导入。
在反汇编程序中打开各种生成的文件显示_main 确实是入口点,并且导入表包含从KERNEL32.dll 导入的ExitProcess(没有名称装饰),但是 Windows 不会加载可执行文件,声称“%1 不是有效的 Win32 应用程序。”
我注意到一个奇怪的事情是,当我在Resource Hacker 打开文件时,添加一个小的嵌入式资源并保存,生成的文件执行没有问题。这让我相信这不是链接步骤本身的问题,而是文件头的问题,因为这应该是过程中唯一改变的部分。删除嵌入的资源并再次保存会导致 Resource Hacker 崩溃并将可执行文件恢复到之前的损坏状态。
代码
; test.asm
global _main
extern _ExitProcess@4
section .text
_main:
push 0
call _ExitProcess@4
尝试失败
-
nasm -fwin32 test.asm & gcc -s test.obj
创建一个正常运行的可执行文件,但还包含我试图避免的所有 CRT 启动代码。 -
nasm -fwin32 test.asm & gcc -s -nostartfiles test.obj
创建一个无效的可执行文件。 -
nasm -fwin32 test.asm & gcc -s -nostdlib test.obj
创建一个无效的可执行文件。 -
nasm -fwin32 test.asm & ld test.obj -e _main
创建一个无效的可执行文件。
所有命令都成功执行,没有控制台输出。我还尝试在gcc 调用中添加-lkernel32 和-Wl,-e_main 的各种组合,但似乎都没有任何效果。
环境
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
【问题讨论】:
-
FWIW,我可以重现这个。将
crtbegin.o添加到链接命令会生成一个正常运行的可执行文件。我不知道 crtbegin 中有什么,但如果你挖掘源代码,那可能就是你能找到答案的地方。也许只是它添加了一个 rdata 部分? -
@DavidWohlferd 很好的观察,添加 .rdata 部分确实使一切变得不同。我可以通过在程序集源中手动添加它来实现这一点。您想将此作为实际答案发布,以便我接受吗?
标签: assembly gcc linker mingw ld