能力值:
( LV12,RANK:230 )
|
-
-
2 楼
得考虑不同编译器的具体实现
|
能力值:
(RANK:260 )
|
-
-
3 楼
单说代码,当然在同样的CPU下是一样的。
不同的在于,程序要执行,就必须被操作系统正确地加载。而操作系统加载一个程序,不是光有个代码就够了的,还需要其它一些信息,这些信息在不同的系统上是不同的,或者说至少格式是不同的。
另一方面,程序运行时要调用到库函数,而不同的操作系统上以不同方式提供这些库,比如C运行时库,在Linux上提供的是glibc,以elf共享库格式提供;在windows上是msvcr,以PE格式提供(DLL)。
不同的操作系统要求链接器以不同的方式将用户程序与操作系统提供的库相链接,所以最终的二进制文件不可以“跨平台”,不过使用模拟器除外,如Linuxg下的wine。
虽然如此,但是在一定程度上,还是可以做到“二进制兼容”的。如果你写了一段程序,只使用了标准的库,比如printf(),而没有使用平台特定的库函数,比如CreateFileA(),那么编译好的目标文件是可以在不同的平台上链接的。只要你的链接器支持对应的文件格式。
虽然Windows平台最终的执行文件必须是PE格式,但目标文件并没有规定必须是COFF的OBJ文件,可以是ELF格式甚至A.OUT格式。GNU的链接器ld具有将ELF格式的.o目标文件与COFF格式的.lib库相链接而产生一个PE文件的能力。
同样,在Linux平台下,也可以将COFF格式的.obj目标文件与ELF格式的.o或.so共享库进行连接链接生成ELF执行文件的。
可以找GNU强大的Binutil的文档来看一下。不得不佩服GNU真是太强大了。
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
但是从cpu的角度去看执行代码应该都是一样的吧。
不管是cl编译的也好, gcc编译的也好,最终生成的代码都是由相同的cpu执行的呀......
估计要重新学习计算机体系结构了......
小弟不才,望大虾指点
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
多谢彭大虾的指点,
也就是说,
int main(int argc, char **argv)
{
printf("aaa\n");
return 0;
}
这样的代码,不调用库, 那编译出来的代码段应该是一样的。
恩, 回去补习计算机体系结构了!
|
能力值:
(RANK:260 )
|
-
-
6 楼
这段代码不是不调用库,而是只调用标准库printf(),而这个函数在不同平台下都提供
所以,对这段程序执行cc -c main.c
输出main.o
你把这个main.o拿到windows下,用MinGW或Cygwin中的ld,使用合适的参数,可以将它连接成为一个windows下的exe程序(控制台)。
而你在windows下用cl /c main.c生成main.obj,同样可以用ld连接到不同的库上。
原理是,虽然obj和o文件格式不一样,但编译器生成的main()函数的代码,大致是一样的,类似于
_main:
push offset const_string ;指向数据区的数据
call 00000000 ;占位,需要链接器重定位(注意,不是加载重定位)
add esp, 4
xor eax, eax
retn
区别只是不同的文,用不同的格式存储而已。而GNU的ld可以识别各种格式,从而处理其中的地址重定位。至于输出什么格式,则取决于传递的参数了。
|
能力值:
(RANK:260 )
|
-
-
7 楼
补充一下,在Linux下用ld就可以链接成windows的pe格式,不需要用Windows下的MinGW的。
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
今天真是长见识了,太感谢彭大侠了!
看来还是看雪的热心人多啊,同样的贴子我在别的论坛挂了3天都没人回复......
|
|
|