Проблемы с построением YASM/NASM Hello World

Я пытаюсь встроить hello.asm в исполняемый файл Windows, но когда я использую предложенные команды для сборки, компоновки и компиляции кода, я получаю ошибки. Будь я использую http://strawberryperl.com/ 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 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

Технические характеристики:

  • YASM 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

3 ответа

Замените свой main() функция с меткой _WinMain@16 как это:

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

Решение в нескольких частях:

  1. Происходила странная вещь: когда я вручную набираю gcc ... чтобы собрать исполняемые файлы, я получаю несколько ошибок в ссылках. Но когда я использовал make чтобы выполнить точно такую ​​же команду, я получил все виды ошибок ссылок. Оказывается, что make.exe из Free Pascal следил за правильным make.exe. Вы можете это исправить, добавив правильный каталог в PATH или удалив приложение-нарушитель. Я не особо использовал Pascal, поэтому я удалил его, и внезапно gcc начал работать лучше.

  2. Сборка Windows NASM/YASM требует префикса имен функций с подчеркиванием (_). Чтобы сохранить ассемблерный код многоплатформенным, опустите в коде подчеркивание и используйте опцию Makefile, чтобы указать nasm / yasm префикс с подчеркиванием при сборке в Windows.

  3. Сборка с руководством ld Звонок, чтобы связать вещи вместе в Windows, не работает. Подставляя gcc исправлены нечетные ошибки ссылки "undefined printf", потому что GCC каким-то образом знает, как с этим разобраться.

  4. Трудно правильно выйти из программы, особенно в многоплатформенном виде. Один из способов установить eax в ноль, а затем вернуться.

Все это отражено в рабочих версиях hello.asm для NASM и YASM на GitHub.

Для простой консоли 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 

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
Другие вопросы по тегам