回 帖 发 新 帖 刷新版面

主题:不同操作系统下的 可执行文件问题,谢谢大家!

大家好,最近小弟在思考一个问题,围绕可执行文件上的,想了很久、也网上搜索很多、问过导师,可结果都不是太满意,找不到一个明确的答案,下面把问题描述如下,希望大家帮忙看一下,同时如果我的文字上有什么不明白的地方,我会在后面解释的。 大家献计献策,问题如下:
1、windows、dos系列可执行文件(如.exe.dll)只能在windows、dos系列下运行;而unix系列的可执行文件(如.out)则只在unix系列
下运行。
    根据网上搜索到的有限信息看,我想造成这样的原因是它们的文件格式是不同的,导致不同的操作系统在加载这些文件所采取的加载方式也不同。
    按照上面的思路,能不能这样说:不管采取什么样的加载方式,对同样功能的程序(比如是打印一个hello world字符串),当被加载完毕之后,此程序对应的内存中内容是否一致?
    2、编译器 编译、连接源文件成可执行文件的问题(比如c语言的编译器)
    在常见的情况下,我用tc编译程序,它直接生成.exe格式的文件,它将符合windows
或着dos的文件格式。但在windows未出现之前,我编译c源文件,它将生成什么样的可执行文件格式呢?
    或者另一种方式是:我在windows下用tc编译出的可执行文件是按照.exe格式生成的,我在linux用gcc编译出的可执行文件是按照.out格式(或其他)生成的。这些可执行文件则依赖他们所在的操作系统。  我的想法是 如果我想用编译器生成一个即不按window格式不按linux格式的可执行文件的话,同时又想把这个“可执行文件”放到内存中可以直接运行,即可让cpu读懂。我是不是需要重新规定“可执行文件”的格式?是否需要重新写一个编译器(或者连接器)呢? 
      3、以上的问题也可以用一个问题概括出来:我想做一个裸机上的程序,那我的程序应该怎么编译?如何让cpu读懂,如何能够被正确的被引导?(用c或者汇编。)在做一个裸机上的程序之前,需要做什么准备工作?等等。

 









回复列表 (共7个回复)

沙发


查汇编指令+调用BIOS?

顺便坐个沙发,我也想知道:-》

板凳

Java solved this problem and compiled the source to byte code, then use JVM (Java Virtual Machine) to interpret it.

For example, you download binary tomcat from apache, unpack it on windows or linux, you can start the server immediately without recompile tomcat.

Now, microsoft .NET use the same concepts, and compile c#, c++, VB, FORTRAN etc, and your c code actually can call fortran byte code to do the job fortran does the best. However, on windows only :(

3 楼

楼主,我现在就在研究这个问题,因为我想TC写个16位的操作系统。
搞了2,3天,我 算终于明白应该要怎么做。(当然,这个也是我自己思考,加猜测,你可以看看,看能和你的想法有共同处,或对你有帮助不)

首先,我认为如果你要用TC来写的话,那麻烦要大的多。TC编译出来的,是com或exe文件,其实他们和在LINUX下我们自己写的代码部分的二进制数据是一样的,可问题在于,TC在编译连接我们的代码时,将他们翻译成汇编,而且在我们代码的外围加了一个壳,这其中就用到了DOS系统调用,而这个壳的具体内容,应该在 cos.obj (这个是微模式下连接的目标库 )中,所以要是你TC写独立于DOS系统的程序(即去掉DOS调用)那你必须要自己重写 cos.obj 等文件的内容,所以你必须得先弄明白 COS.OBJ 做了些什么,怎么做的。(呵呵,我现在也很郁闷的,要是你有 cos.obj 的源码发给我看看,要是你用反汇编,估计也很难看懂)

再则,就是使用 linux 下的 elf 文件格式,这个也是大多数,系统编写爱好者选择的格式。用elf在裸机上跑就不用使用 LINUX 的系统调用,因为LINUX也是根据 elf 的 ELF头,程序表头等信息将文件的可执行数据给放在对应的内存块中,然后将IP指向那块内存即可,所以我们可以参照来做。


所以具我自己的猜测归纳起来就是:TC在编译的时候给代码加了壳,而这个壳中却使用了DOS调用,所以你必须想办法重写 cos.obj 文件,让编译出的程序脱离DOS系统。做起来有难度,可他可以直接在WIN平台开发系统,这样比较方便。

而用ELF 格式,只要你了解了他的格式,做起来也就简单。因为他不需要系统调用,而是直接的二进制可执行代码。可用他你必须在LINUX下去实现,要不真的装可LINUX,要不在WIN平台用虚拟机来装,这样达建平台得花点力气。


我也还在实验中,其实就我个人而言,我比较钟情 用TC来做。毕竟我们绝大多数编程者都是通过他入门的,所以要是你解决了TC下COS。OBJ 的难题,记得发给贴子,考试我一声,先谢啦啊!

4 楼

楼上说的加壳问题,我还不太清楚是不是加了功能调用的壳

不过根据个人的使用经验上看,比如说做一个引导文件
把生成的.exe文件复制到引导扇区中,它不能执行。(事实上.exe文件的大小都大于512b,而引导扇区需要小于512b)
而把生成的.com文件弄到引导扇区中,却能得到与假设的结果一致。
把生成的.out文件则也可以!

实在不清楚为什么那样就行,这样就不行,还是希望大家多多关注,多多发贴。
好困惑……

5 楼

我已经成功了,要是感兴趣,可以关注我的BLOG

http://blog.tom.com/blog/blogindex.php?BloggerID=616233

6 楼

呵呵,时隔两个多月,有些东西总算是搞明白些了,
同时也非常谢谢这个论坛给我的帮助

/*************************
1、windows、dos系列可执行文件(如.exe.dll)只能在windows、dos系列下运行;而unix系列的可执行文件(如.out)则只在unix系列下运行。
    根据网上搜索到的有限信息看,我想造成这样的原因是它们的文件格式是不同的,导致不同的操作系统在加载这些文件所采取的加载方式也不同。
    按照上面的思路,能不能这样说:不管采取什么样的加载方式,对同样功能的程序(比如是打印一个hello world字符串),当被加载完毕之后,此程序对应的内存中内容是否一致?
/*************************

这个问题,并非完全仅是加载的问题,在不同的系统编译连接的时候已经“分头行动”了。比如说一个程序是调用printf打印hello world 
那么在windows下编译连接,则调用针对windows的c语言库下的printf的二进制指令实现向显示器输出字符串,而在linux下,则连接的是linux下的c语言库下的printf的二进制代码。

这里的问题就归结于 windows下的c库的printf 与 linux下的c库的printf 对应的代码是否一致的问题啦,这点,关于编译器c库的实现,是编译器厂商自己做的,(我们大家只管调用即可)。
不同的cpu 下的同一个功能的函数对应的代码指令是不一样的;
即使同一个cpu下的不同厂商的相同功能的函数,对应的代码肯定也不可能相同。
(tc是由borland,gcc则是由gnu)虽然都共同运行在某一个相同的cpu里(x86)。

当然加载的话,则有重定位的问题,但是这个不属于根本的,因为代码已经生成了。
只要cpu的pc找到那块代码就行

7 楼


呵呵
久违的帖子了。
在2006-5-12写的,现在是2009-9-18
三年多了。

难得,难得。

在此作个记号。

这些问题,都不是问题。



我来回复

您尚未登录,请登录后再回复。点此登录或注册