我在64位计算机上的Win7下使用Cygwin。
以下程序以64位模式编译,没有任何问题。
select x.* from
(
select empId from employees
group by empId
having count(*) > 1
) x
where empId > 0
having count(*) > 1
order by x.empId
fetch next 10 rows only
runme: main.cpp asm.o
g++ main.cpp asm.o -o executable
asm.o: asm.asm
nasm -f elf64 asm.asm -o asm.o
section .data
section .bss
section .text
global GetValueFromASM
GetValueFromASM:
mov eax, 9
ret
但是,我想以32位模式进行编译。因此,我将#include <iostream>
using namespace std;
extern "C" int GetValueFromASM();
int main()
{
cout<<"GetValueFromASM() returned = "<<GetValueFromASM()<<endl;
return 0;
}
更改为elf64
,新的makefile如下所示:
elf
但是,出现以下错误:
runme: main.cpp asm.o
g++ main.cpp asm.o -o executable
asm.o: asm.asm
nasm -f elf asm.asm -o asm.o
可能是什么原因?
如何解决这个问题?
编辑1 :我在$ make
nasm -f elf asm.asm -o asm.o
g++ main.cpp asm.o -o executable
/usr/lib/gcc/x86_64-pc-cygwin/7.4.0/../../../../x86_64-pc-cygwin/bin/ld: i386
architecture of input file `asm.o' is incompatible with i386:x86-64 output
collect2: error: ld returned 1 exit status
make: *** [makefile:4: runme] Error 1
中添加了-m32
选项。现在,错误如下:
g++
答案 0 :(得分:2)
正如我在评论中指出的那样,[SO]: Can you run a 32 bit Cygwin application in a 64 bit installation? (@CristiFati's answer)包含许多有用的信息。
我想从两个观察开始:
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 ,所以我已经在 asm.o 上构建了 32bit 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 vs。 _ GetValueFromASM 不匹配),发生在 Win (仅 32bit )上的名称修改问题(尽管错误消息不是很有帮助)。 >)。
[Wikipedia]: Executable and Linkable Format做到了这一点(还有其他解决方案,但看起来不太好)。您所需要做的就是将 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