Как я указал в комментарии, [SO]: Можете ли вы запустить 32-битное приложение Cygwin в 64-битной установке? (@ Ответ CristiFati) содержит много полезной информации.
Хочу начать с 2 наблюдений:
- gcc 64bit требуется флаг -m32 (и наоборот: gcc 32bit нужен -m64 ), иначе они сгенерируют двоичные файлы, соответствующие их архитектуре CPU . Файлы объектов 32bit и 64bit ( .o ) несовместимы (при передаче компоновщику) и завершатся ошибкой
- Cygwin (включая gcc ) использует Win формат исполняемых файлов или PE ( [Википедия ]: Переносимый исполняемый файл ). nasm форматы вывода ( elf32 и elf64 ) генерировать ELF s ( [Wikipedia] : Исполняемый и связываемый формат ). Я не знаю, как это работает (очевидно, где-то происходит преобразование формата, но я не знаю, где именно). Ради строгости, я буду использовать их Win ( win32 и win64 ), которые также работают (проверка
nasm -hf
)
Я тоже сталкивался с таким же поведением на Cygwin 32 (до того, как вы отредактировали вопрос):
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q055497459]> ~/sopr.sh
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***
[prompt]> uname -a
CYGWIN_NT-10.0-WOW cfati-5510-0 2.11.2(0.329/5/3) 2018-11-08 14:30 i686 Cygwin
[prompt]>
[prompt]> ls
asm.asm asm.o builds main.cpp Makefile
[prompt]> make
MAKE Version 5.2 Copyright (c) 1987, 1998 Inprise Corp.
g++ -o main.o -c main.cpp
g++ -o executable main.o asm.o -lstdc++
main.o:main.cpp:(.text+0x5a): undefined reference to `GetValueFromASM'
collect2: error: ld returned 1 exit status
** error 1 ** deleting executable
Я должен отметить, что у меня не установлено nasm , поэтому я построил ( 32bit ) asm.o на Cygwin 64 . Поскольку переключение между терминалами раздражает, я полностью переключился на Cygwin 64 , где у меня есть 32bit gcc ( i686-pc-cygwin-gcc ) установлено.
Я также изменил 2 ваших файла ( Makefile может быть улучшен, но сейчас это не главное).
main.cpp
#include <iostream>
using namespace std;
extern "C" int GetValueFromASM();
int main() {
cout << "sizeof(void*): " << sizeof(void*) << endl;
cout << "GetValueFromASM() returned: " << GetValueFromASM() << endl;
return 0;
}
Makefile
.PHONY: all clean executable
objects = main.o asm.o
cpp = g++
cpp = i686-pc-cygwin-gcc
#m32_flag = -m32
asm_out_format = win32
#link_verbose_flag = -v
all: executable
clean:
rm -f $(objects) executable
executable: $(objects)
$(cpp) $(link_verbose_flag) $(m32_flag) -o $@ $(objects) -lstdc++
asm.o: asm.asm
nasm -f $(asm_out_format) -o $@ $?
main.o: main.cpp
$(cpp) $(m32_flag) -o $@ -c $?
После нескольких попыток я определил причину проблемы:
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q055497459]> ~/sopr.sh
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***
[prompt]> uname -a
CYGWIN_NT-10.0 cfati-5510-0 3.0.5(0.338/5/3) 2019-03-31 11:17 x86_64 Cygwin
[prompt]>
[prompt]> ls
asm.asm builds main.cpp Makefile
[prompt]> make
i686-pc-cygwin-gcc -o main.o -c main.cpp
nasm -f win32 -o asm.o asm.asm
i686-pc-cygwin-gcc -o executable main.o asm.o -lstdc++
main.o:main.cpp:(.text+0x5a): undefined reference to `GetValueFromASM'
collect2: error: ld returned 1 exit status
make: *** [Makefile:17: executable] Error 1
[prompt]>
[prompt]> nm -S asm.o | grep GetValueFromASM
00000000 T GetValueFromASM
[prompt]>
[prompt]> nm -S main.o | grep GetValueFromASM
U _GetValueFromASM
Итак (обратите внимание на GetValueFromASM против _ GetValueFromASM несоответствие), это вопрос искажение имени (хотя сообщение об ошибке не очень полезно), которое происходит на Win ( 32bit только ).
[SO]: Добавление начальных подчеркиваний к символам сборки с помощью GCC на Win32? (ответ @ ephemient) добились цели (есть и другие решения, но они выглядят не очень красиво). Все, что вам нужно сделать, это изменить GetValueFromASM объявление на :
extern "C" int GetValueFromASM() asm ("GetValueFromASM");
и после сборки (на Cygwin 64 ):
[prompt]> uname -a
CYGWIN_NT-10.0-WOW cfati-5510-0 2.11.2(0.329/5/3) 2018-11-08 14:30 i686 Cygwin
[prompt]>
[prompt]> file executable.exe
executable.exe: PE32 executable (console) Intel 80386, for MS Windows
[prompt]> ./executable.exe
sizeof(void*): 4
GetValueFromASM() returned: 9