mcandre
mcandre

Reputation: 24612

Trouble building YASM/NASM Hello World

I'm trying to build hello.asm into a Windows executable, but when I use the suggested commands for assembling, linking, and compiling the code, I get errors. Whether I'm using Strawberry Perl's GCC or MinGW's GCC, both give errors for the same YASM/NASM code.

Here are the traces. Either I'm doing something wrong in my Makefile or .ASM, or the linking process is buggy. Either way, I'd like someone to help me resolve the errors.

I get the same result whether I use nasm or yasm to assemble the object file.

Strawberry Perl GCC Trace:

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 Trace:

$ 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

Specs:

Upvotes: 0

Views: 5112

Answers (3)

Raymond Wu
Raymond Wu

Reputation: 354

Replace your main() function with label _WinMain@16 like this:

main.asm

    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);
    }

Makefile

all:
    rm -f *.o
    gcc -c foo.c
    nasm -f win32 -o main.o main.asm
    gcc -o main.exe main.o foo.o

Upvotes: 4

mcandre
mcandre

Reputation: 24612

A solution in several parts:

  1. A strange thing was happening: When I manually type gcc ... to build the executables, I get few link errors. But when I used make to run the exact same command, I got all kinds of link errors. It turns out that Free Pascal's make.exe was shadowing the proper make.exe. You can either fix this by promoting the proper directory in PATH, or uninstalling the offending application. I didn't have much use for Pascal, so I uninstalled it and suddenly gcc started working better.

  2. Windows NASM/YASM assembly requires prefixing function names with underscore (_). In order to keep the assembly code multiplatform, omit the underscores in the code, and use a Makefile option to tell nasm/yasm to prefix with an underscore when building in Windows.

  3. Building with a manual ld call to link the stuff together in Windows does not work. Substituting gcc fixed the odd "undefined printf" link errors, because GCC somehow knows how to sort this out.

  4. It's difficult to properly exit a program, espcially in a multiplatform way. One way is to set eax to zero and then return.

All of this is reflected in working versions of hello.asm for NASM and YASM, at GitHub.

Upvotes: 1

Gunner
Gunner

Reputation: 5884

For a simple windows console hello: 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 

makefile:

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

Upvotes: 0

Related Questions