0

我正在尝试将hello.asm构建到 Windows 可执行文件中,但是当我使用建议的命令来组装、链接和编译代码时,我得到了错误。无论我使用的是Strawberry Perl的 GCC 还是MinGW的 GCC,都会对相同的 YASM/NASM 代码给出错误。

这是痕迹。要么我在 Makefile 或 .ASM 中做错了,要么链接过程有问题。无论哪种方式,我都希望有人帮助我解决错误。

无论我使用 nasm 还是 yasm 来组装目标文件,我都会得到相同的结果。

草莓 Perl GCC 跟踪:

C:\> make
nasm -f win32 -l hello.lst hello.asm
gcc -o hello hello.o
ld: cannot find crt1.o: No such file or directory
ld: cannot find -lmingw32
ld: cannot find -lgcc
ld: cannot find -lmoldname
ld: cannot find -lcrtdll
ld: cannot find -luser32
ld: cannot find -lkernel32
ld: cannot find -ladvapi32
ld: cannot find -lshell32
ld: cannot find -lmingw32
ld: cannot find -lgcc
ld: cannot find -lmoldname
ld: cannot find -lcrtdll
make: *** [hello] Error 1

MinGW GCC 跟踪:

$ make
gcc -o hello hello.o
c:/mingw/bin/../lib/gcc/mingw32/4.5.2/../../../libmingw32.a(main.o):main.c:(.text+0x104): undefined reference to `WinMain@16'
collect2: ld returned 1 exit status
make: *** [hello] Error 1

眼镜:

  • 雅思 1.2.0
  • NASM 2.10.05
  • 草莓 Perl gcc 4.4.3
  • MinGW gcc 4.5.2
  • 草莓 Perl 5.12
  • MinGW 0.1
  • Windows 7 专业版 x64
  • MacBook Pro 2009
4

3 回答 3

4

main()用这样的标签替换你的函数_WinMain@16

主程序

    section .text
    extern  _foo

;--------------------------------------------------
; main()
; 在 Win32 環境下, _WinMain@16 為程式進入點
;--------------------------------------------------

    global  _WinMain@16
_WinMain@16:
    ; foo(2,3)
    ; 呼叫時, 參數為堆疊順序 (先進後出)
    push    DWORD 3     ; b=3
    push    DWORD 2     ; a=2
    call    _foo

    ; 堆疊復原
    pop     eax
    pop     eax
    ret

foo.c

    #include <stdio.h>

    void foo(int a, int b) {
         printf("%d + %d = %d\n", a, b, a+b);
    }

生成文件

all:
    rm -f *.o
    gcc -c foo.c
    nasm -f win32 -o main.o main.asm
    gcc -o main.exe main.o foo.o
于 2012-11-22T07:59:28.620 回答
1

分几个部分的解决方案:

  1. 发生了一件奇怪的事情:当我手动键入gcc ...构建可执行文件时,我得到的链接错误很少。但是当我make以前运行完全相同的命令时,我得到了各种链接错误。事实证明,Free Pascal 的 make.exe 隐藏了正确的 make.exe。您可以通过提升 PATH 中的正确目录或卸载有问题的应用程序来解决此问题。我对 Pascal 没有太多用处,所以我卸载了它,突然 gcc 开始工作得更好了。

  2. Windows NASM/YASM 程序集需要在函数名称前加上下划线 ( _)。为了保持汇编代码多平台,在代码中省略下划线,并使用 Makefile 选项告诉 nasm/yasm 在 Windows 中构建时以下划线为前缀。

  3. 在 Windows 中通过手动调用将这些东西链接在一起进行构建是ld行不通的。替换gcc修复了奇怪的“未定义的 printf”链接错误,因为 GCC 不知何故知道如何解决这个问题。

  4. 很难正确退出程序,尤其是在多平台方式下。一种方法是设置eax为零然后返回。

所有这些都反映在 GitHub 上用于NASMYASM的 hello.asm 的工作版本中。

于 2012-09-20T18:44:03.833 回答
0

对于一个简单的 Windows 控制台你好:hello.asm

extern  printf, ExitProcess

SECTION     .data
szHello db  "Hello there!", 0

SECTION     .text
StartHello:
    push    szHello
    call    printf
    add     esp, 4 

    push    0
    call    ExitProcess 

生成文件:

hello: hello.obj
    GoLink.exe  /console /entry StartHello hello.obj kernel32.dll msvcrt.dll  

hello.obj: hello.asm
    nasm -f win32 hello.asm -o hello.obj
于 2012-09-20T02:29:50.600 回答