Проблемы со сборкой YASM / NASM Hello World

Я пытаюсь встроить hello.asm в исполняемый файл Windows, но когда я использую предложенные команды для сборки, компоновки и компиляции кода, я получаю ошибки. Независимо от того, использую ли я GCC Strawberry Perl или GCC MinGW, оба выдают ошибки для одного и того же кода YASM / NASM.

Вот следы. Либо я делаю что-то не так в моем Makefile или .ASM, либо в процессе компоновки есть ошибки. В любом случае, мне бы хотелось, чтобы кто-нибудь помог мне исправить ошибки.

Я получаю один и тот же результат независимо от того, использую ли я nasm или yasm для сборки объектного файла.

След Strawberry 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

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

  • 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 г.

person mcandre    schedule 20.09.2012    source источник
comment
Какая ОС? Я вижу, у вас есть Win7 и MAC. Для Windows используйте GoLink в качестве компоновщика. Вы экспортировали свой стартовый ярлык?   -  person Gunner    schedule 20.09.2012
comment
Я хочу использовать ld или gcc для ссылки; GCC более многоплатформенный, доступен для Windows через установщик MinGW.   -  person mcandre    schedule 20.09.2012
comment
@Gunner, сейчас я использую Windows 7, хотя мне нравится двойная загрузка, поэтому я использую оборудование MacBook Pro. И я хочу иметь возможность собирать и связывать один и тот же код YASM / NASM независимо от того, какую ОС я использую, потому что YASM и NASM являются мультиплатформенными.   -  person mcandre    schedule 20.09.2012
comment
Вообще-то, нет. Ассемблер / компоновщик мультиплатформенный, но код, который вы пишете, не ...   -  person Toribio    schedule 20.09.2012
comment
@ FlávioToribio, не могли бы вы показать код, который будет работать как в Windows, так и в Linux?   -  person mcandre    schedule 20.09.2012
comment
@mcandre, AFAIK, это невозможно, см. этот вопрос   -  person Toribio    schedule 20.09.2012
comment
Конечно возможно! Вот урок, который я написал с использованием nasm и gtk. Работает в Linux и Windows www.dreamincode.net/forums/topic/292403-nasm-cross-os-app-for-linuxwindows-using-gtk/   -  person Gunner    schedule 20.09.2012
comment
Это хороший учебник, но вы не использовали инструкции и регистры, зависящие от ОС, которых, я думаю, у Assembly больше всего ... push, pop, add, lea, mov, call и т. Д. Просто совпадают для двух ОС, и вы используете многоплатформенную библиотеку, но, например, если вы попытаетесь открыть гнездо для CD-ROM, вам придется использовать разные функции, библиотеки, прерывания и т. д.   -  person Toribio    schedule 20.09.2012
comment
@ FlávioToribio, вы все равно можете обойти это с помощью препроцессоров, если процесс сборки похож на C.   -  person mcandre    schedule 20.09.2012
comment
@Gunner, это отличный урок! Мне нравится, как вы используете один Makefile для нескольких операционных систем. Не могли бы вы опубликовать более простой вариант, который просто печатает Hello World в Windows, Mac и Linux? Я был бы особенно признателен, если бы вы показали, как это сделать с помощью набора инструментов GCC во всех этих случаях, вместо того, чтобы требовать MSVC ++ для Windows.   -  person mcandre    schedule 20.09.2012
comment
@ Flávio уверен, что вы можете написать кросс-кодовый код, который использует условную ассемблер, но это кошмар для обновления и исправления ошибок. Лучше всего использовать многоплатформенную библиотеку. Я определенно могу извлечь лоток для компакт-диска в Windows и Linux с помощью GIO из GTK. Объясните, какие регистры специфичны для ОС?   -  person Gunner    schedule 21.09.2012


Ответы (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
person Raymond Wu    schedule 22.11.2012
comment
Спасибо, Эчилон! Это мой 1-й пост на stackoverflow, ваш синтаксис очень полезен. - person Raymond Wu; 23.11.2012

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

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

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

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

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

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

person mcandre    schedule 20.09.2012
comment
Спасибо за №2! --prefix=_ это то, что мне нужно. - person Jonathon Reinhart; 03.11.2017

Для простой консоли Windows 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
person Gunner    schedule 20.09.2012
comment
Hello World, который он пытается скомпилировать, использует вызовы прерывания, а не библиотеки C для печати сообщения ... - person Toribio; 20.09.2012
comment
Ну, вы не можете использовать прерывания Linux в окнах, которые использует его связанный код - person Gunner; 20.09.2012
comment
Именно поэтому у меня нет для него ответа. Он пытается скомпилировать код для Linux, но говорит, что использует Windows, и даже пытается скомпилировать на elf ... - person Toribio; 20.09.2012
comment
@ FlávioToribio, да, elf был неправильным форматом. С тех пор я изменил Makefile, чтобы выбрать правильный формат для текущего компьютера. github.com/mcandre/mcandre/blob/master/yasm/hello/ Makefile - person mcandre; 20.09.2012