You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译汇编代码时出现undefined reference to `WinMain@16'错误求助

解决MinGW下汇编代码链接报错undefined reference to 'WinMain@16'的问题

问题描述

我通过GCC的-S选项将自行编写的C语言快速排序函数编译为汇编代码,编译该汇编代码时GCC报错:undefined reference to 'WinMain@16'。我对汇编完全不了解,怀疑该问题与操作系统相关。另外,手动编译项目时无报错,但通过CMake构建时出现该错误,相关代码及环境信息如下:

汇编代码

.file   "quickSort.c"
    .text
    .globl  _partition
    .def    _partition; .scl    2;  .type   32; .endef
_partition:
LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $16, %esp
    movl    16(%ebp), %eax
    leal    0(,%eax,4), %edx
    movl    8(%ebp), %eax
    addl    %edx, %eax
    movl    (%eax), %eax
    movl    %eax, -12(%ebp)
    movl    12(%ebp), %eax
    movl    %eax, -4(%ebp)
    movl    12(%ebp), %eax
    movl    %eax, -8(%ebp)
    jmp L2
L4:
    movl    -8(%ebp), %eax
    leal    0(,%eax,4), %edx
    movl    8(%ebp), %eax
    addl    %edx, %eax
    movl    (%eax), %eax
    cmpl    %eax, -12(%ebp)
    jl  L3
    movl    -8(%ebp), %eax
    leal    0(,%eax,4), %edx
    movl    8(%ebp), %eax
    addl    %edx, %eax
    movl    (%eax), %eax
    movl    %eax, -16(%ebp)
    movl    -4(%ebp), %eax
    leal    0(,%eax,4), %edx
    movl    8(%ebp), %eax
    addl    %edx, %eax
    movl    -8(%ebp), %edx
    leal    0(,%edx,4), %ecx
    movl    8(%ebp), %edx
    addl    %ecx, %edx
    movl    (%eax), %eax
    movl    %eax, (%edx)
    movl    -4(%ebp), %eax
    leal    0(,%eax,4), %edx
    movl    8(%ebp), %eax
    addl    %eax, %edx
    movl    -16(%ebp), %eax
    movl    %eax, (%edx)
    addl    $1, -4(%ebp)
L3:
    addl    $1, -8(%ebp)
L2:
    movl    -8(%ebp), %eax
    cmpl    16(%ebp), %eax
    jl  L4
    movl    -4(%ebp), %eax
    leal    0(,%eax,4), %edx
    movl    8(%ebp), %eax
    addl    %edx, %eax
    movl    16(%ebp), %edx
    leal    0(,%edx,4), %ecx
    movl    8(%ebp), %edx
    addl    %ecx, %edx
    movl    (%eax), %eax
    movl    %eax, (%edx)
    movl    -4(%ebp), %eax
    leal    0(,%eax,4), %edx
    movl    8(%ebp), %eax
    addl    %eax, %edx
    movl    -12(%ebp), %eax
    movl    %eax, (%edx)
    movl    -4(%ebp), %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE0:
    .globl  _quick_sort
    .def    _quick_sort;    .scl    2;  .type   32; .endef
_quick_sort:
LFB1:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $40, %esp
    movl    12(%ebp), %eax
    cmpl    16(%ebp), %eax
    jge L9
    movl    16(%ebp), %eax
    movl    %eax, 8(%esp)
    movl    12(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    _partition
    movl    %eax, -12(%ebp)
    movl    -12(%ebp), %eax
    subl    $1, %eax
    movl    %eax, 8(%esp)
    movl    12(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    _quick_sort
    movl    -12(%ebp), %eax
    leal    1(%eax), %edx
    movl    16(%ebp), %eax
    movl    %eax, 8(%esp)
    movl    %edx, 4(%esp)
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    _quick_sort
    jmp L6
L9:
    nop
L6:
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE1:
    .ident  "GCC: (MinGW.org GCC Build-2) 9.2.0"

C语言代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#define LN 100
#define ERROR(...) (printf(__VA_ARGS__))

extern void quick_sort(int *array, int x, int y);

// here is the rest of the code 

int main(int argc, char *argv[]) {
    
    int left_border = INT_MIN, right_border = INT_MAX;     
    int return_code = read_border(argv, argc, &left_border, &right_border);

    if (return_code != 0) {
        printf("%d\n", return_code);
        return return_code;            
    } 
    int array[LN] = {0}, stdout_array[LN] = {0}, stderr_array[LN] = {0};  
    int count_elements = read_array(array, stdout_array, stderr_array, left_border, right_border);
    int sorted_array[LN] = {0};
    _memccpy(sorted_array, array, array[count_elements-1] - '0', count_elements * sizeof(int));
    quick_sort(sorted_array, 0, count_elements-1);
    int answer = count_sorted_elements(array, sorted_array, count_elements);

    print_stdout_or_stderr(stdout_array, stderr_array, array[0]);
    printf("%d", answer);
    return answer;
}

CMakeLists.txt

file(GLOB_RECURSE C_SOURCES ./*.c)
file(GLOB_RECURSE ASM_SOURCES ./*.s)

add_executable(main ${C_SOURCES} ${ASM_SOURCES})

if(MSVC)
  target_compile_options(main PRIVATE /W4 /WX)
else()
  target_compile_options(main PRIVATE -Wall -Wextra -pedantic -Werror)
endif()

GCC版本

MinGW.org GCC Build-2 9.2.0


解决建议

1. 修复CMake的文件匹配逻辑

file(GLOB_RECURSE)的匹配规则容易引入冗余文件:

  • 如果原quickSort.c还在目录中,CMake会同时编译C版和汇编版的快速排序函数,导致符号冲突,链接器无法识别正确的main入口。
  • 也可能出现带有main函数的C文件未被正确匹配的情况。

解决方法:

  • 移除目录中的quickSort.c,避免重复编译;
  • 替换GLOB_RECURSE为明确的文件名列表,例如:
    set(C_SOURCES main.c) # 替换为你的main函数所在文件名
    set(ASM_SOURCES quickSort.s)
    
  • 可以在CMakeLists.txt中添加调试语句,确认文件是否被正确识别:
    message("C_SOURCES: ${C_SOURCES}")
    message("ASM_SOURCES: ${ASM_SOURCES}")
    

2. 明确指定项目为C语言编译

如果CMake默认按C模式编译,会导致函数符号修饰规则变化(C会给函数名添加额外修饰),进而出现入口函数找不到的问题。

解决方法:
在CMakeLists.txt开头添加:

project(MyProject C)
set(CMAKE_C_STANDARD 99)

强制项目按C语言标准编译,确保汇编代码中的_quick_sort、_partition符号与C代码中的声明匹配。

3. 理解WinMain@16错误的本质

Windows平台下,链接器默认:

  • 控制台程序的入口是main函数;
  • GUI程序的入口是WinMain函数。

当链接器找不到main函数时,会尝试寻找WinMain,找不到就抛出该错误。你的手动编译正常,说明手动命令正确包含了main所在文件和汇编文件,而CMake构建时大概率漏掉了main文件或出现符号冲突。

4. 对比手动编译与CMake的编译命令

通过查看CMake实际执行的编译链接命令,定位差异:

  • 如果使用Makefile生成器,执行:make VERBOSE=1
  • 如果使用Ninja生成器,执行:ninja -v

将输出的命令与你的手动编译命令(例如gcc main.c quickSort.s -o main)对比,检查是否缺少文件、链接选项错误等问题。


内容的提问来源于stack exchange,提问作者just_name

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:01:17