Проблемы с построением 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
Решение в нескольких частях:
Происходила странная вещь: когда я вручную набираю
gcc ...
чтобы собрать исполняемые файлы, я получаю несколько ошибок в ссылках. Но когда я использовалmake
чтобы выполнить точно такую же команду, я получил все виды ошибок ссылок. Оказывается, что make.exe из Free Pascal следил за правильным make.exe. Вы можете это исправить, добавив правильный каталог в PATH или удалив приложение-нарушитель. Я не особо использовал Pascal, поэтому я удалил его, и внезапно gcc начал работать лучше.Сборка Windows NASM/YASM требует префикса имен функций с подчеркиванием (
_
). Чтобы сохранить ассемблерный код многоплатформенным, опустите в коде подчеркивание и используйте опцию Makefile, чтобы указать nasm / yasm префикс с подчеркиванием при сборке в Windows.Сборка с руководством
ld
Звонок, чтобы связать вещи вместе в Windows, не работает. Подставляяgcc
исправлены нечетные ошибки ссылки "undefined printf", потому что GCC каким-то образом знает, как с этим разобраться.Трудно правильно выйти из программы, особенно в многоплатформенном виде. Один из способов установить
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