接上节,程序头可以自定义,只要我们按照自己定义的格式去解析就行。也许我光这么一说,很多同学还是不能彻底明白如何自定义文件头,因为大多数同学都是用高级语言来写程序,即使用了偏底层的c语言,不同平台的c编译器也会根据系统平台自动添加文件头,不给咱们亲手体验自定义程序头的机会。汇编语言非常 灵活,所以用它来构建任意文件格式则是非常方便的。书看到这里,我估计您已经发现我是个非常体贴的人,哈哈,所以给大家呈上以下代码来演示自定义文件头,请见以下的汇编程序代码:

[work@localhost book]$ cat -n header.S1 header:2     program_length  dd program_end-program_start3   start_addr  dd program_start4  ;;;;;;; 以上是文件头,以下是文件体 ;;;;;;;5  body:6  program_start:7  mov ax, 0x12348     jmp $9 program_end:10
[work@localhost book]$

以上测试代码header.S,经编译后生成的文件是header.bin,编译命令是nams –o header.bin header.S,所以header.bin依然是纯二进制文件。但此纯二进制文件的程序入口并不是文件开头,这和咱们的loader.bin很像,mbr是跳到loader.bin的中间某部分去执行。假设header.S是被调用的程序,调用方知道header.S的前8字节是程序头,在这8字节中,前4字节用来标明程序尺寸大小,后4字节用来指明程序的入口地址,也就是该程序的第一条指令地址。从8字节后到文件结束为文件体。在调用方程序已经了解此文件格式后,它可以这样做:

  1. 将header.bin前8字节的内容读到内存,前4字节是程序体长度,后4字节是程序的入口地址。
  2. 将header.bin开头偏移8字节的地方做为起始,将header.bin文件尾,即开头偏移(8+程序体长度)个字节的地方做为终止。
  3. 将起始至终止之间的程序体复制到入口地址
  4. 转到入口地址处执行

您看,被调用方header.bin被设计成这样文件格式,调用方就可以自由处理啦。为了验证文件格式,大家看下header.bin生成的二进制文件真实内容,前8字节用了两个下划线分别区分了两个程序头属性,即program_length是0x00000005,start_addr是0x00000008。顺序是反着的,小端字节序。B83412是mov ax,0x1234指令,EBFE则对应的是jmp $。

当然这仅仅是用来演示,目的是起到抛砖引玉的作用,说了这些是为了引出后面咱们要介绍的文件格式。

自己设计的文件头自己当然认识,但这毕竟不通用,我们需要选择一种流行的文件格式,咱们是在linux下用c语言编程,其编译器gcc生成的是elf文件格式,咱们在下一节展开elf可执行文件格式的内容。

本内容摘自《操作系统真象还原》

一步步编写操作系统 48 二进制程序的加载方式相关推荐

  1. 一步步编写操作系统 48 加载内核1

    其实,我们等了这一刻好久好久,即使我不说,大家也有这样的认识,linux内核是用c 语言写的,咱们肯定也要用c语言.其实...说点伤感情的话,今后的工作只是大部分(99%)都要用c语言来写,还有一些要 ...

  2. 一步步编写操作系统 47 48 二进制程序运行方式

    操作系统并不是在功能上给予用户的支持,这种支持是体现在机制上.也就是说,单纯的操作系统,用户拿它什么都做不了,用户需要的是某种功能.而操作系统仅仅是个提供支持的平台. 虽然我们是模仿linux来写一个 ...

  3. 一步步编写操作系统 71 直接操作显卡,编写自己的打印函数71-74

    一直以来,我们在往屏幕上输出文本时,要么利用bios中断,要么利用系统调用,这些都是依赖别人的方法.咱们还用过一个稍微有点独立的方法,就是直接写显存,但这貌似又没什么含量.如今我们要写一个打印函数了, ...

  4. 一步步编写操作系统 69 汇编语言和c语言共同协作 70

    由于有了上一节的铺垫,本节的内容相对较少,这里给大家准备了两个小文件来实例演示汇编语言和c语言相互调用. 会两种不同语言的人,只是掌握了同一件事物的两种表达方式.人在学习一种新语言时,潜意识里是建立了 ...

  5. 一步步编写操作系统 62 函数调用约定

    由于我们要将c语言和汇编语言结合编程啦,所以一定会存在汇编代码和c代码相互调用的问题,有些事情还是要提前交待给大家的,本节就是要给大家说下函数调用规约中的那些事儿. 函数调用约定是什么? 调用约定,c ...

  6. 一步步编写操作系统 32 linux内核获取内存容量的方法

    操作系统是计算机硬件的管家,它不仅要知道自己的安装了哪些硬件,还得给出有效得当的管理措施,按照预定的一套管理策略使硬件资源得到合理的运用.但管理策略只是逻辑上的东西,是操作系统自圆其说的一套管理资源的 ...

  7. 一步步编写操作系统 10 cpu的实模式

    cpu的实模式 由于mbr在实模式下工作--什么?什么是实模式?这时候有同学打断了我.我心想,这下好办了--哈哈,没有啦,开个玩笑而已.我们这里所说的实模式其实就是8086 cpu的工作环境.工作方式 ...

  8. JAVA入门级教学之(JAVA程序的加载和运行)

    JAVA程序的加载和运行 多思考多动脑(边参考文章最后的示意图,边按步骤理解) 1.JAVA程序的加载和运行包括两个非常重要的阶段: 编译阶段 运行阶段 2.我们先来了解一下什么是编译阶段: 首先,我 ...

  9. QT程序启动加载流程简介

    1. QT应用程序启动加载流程简介 1.1      QWS与QPA启动客户端程序区别 1.1.1   QWS(Qt Window System)介绍 QWS(Qt Windows System)是Q ...

最新文章

  1. 《数学建模:基于R》一一2.2 方差分析
  2. 9.0 C++远征:对象成员
  3. 群星巨型计算机事件,群星 三种特殊事件介绍 特殊事件有几种
  4. 为什么Spring Boot项目引入依赖的时候可以不指定依赖的版本号
  5. java jboss_记录JAVAWEB部署到JBOSS中遇到的问题
  6. C++ 11 在 Qt 5 中的应用
  7. [C#.NET 拾遗补漏]09:数据标注与数据校验
  8. 服务网格:Istio和AWS App Mesh
  9. anaconda python删除pyltp_Anaconda使用
  10. java moneyutils_java中每月等额与先息后本计算
  11. awk分割列 输出时间相关
  12. linux如何检测文件完整,shell脚本实现linux系统文件完整性检测
  13. SVPWM matlab建模
  14. OSPF协议单域配置实例
  15. mappedBy reference an unknown target entity property错误
  16. springboot 整合 ftps
  17. python 读取excel表内容:以获取高铁站点经纬度为例子
  18. 年均科研经费 4000 万,教授没有发论文压力,不必教课,这才是神仙科研生活!...
  19. 基于cooja的RPL OF的修改与仿真
  20. 单机大天使服务器端修改商店,《大天使之剑h5》变态单机版最新开服_无限钻石打造最强阵容_满V公益私服...

热门文章

  1. 数据结构(二)之算法基础
  2. murmurhash
  3. 不同page页面选择不同页面模板的方法
  4. ORACLE EBS 多账套总结
  5. 67、ulimit的使用
  6. 基于三值图像的车牌识别测试程序发布
  7. Nsis 使用1-- 依条件显示自定义页面 custom page on condition
  8. 第二课 决策树与随机森林
  9. matlab 控制实验指导,智能控制系统-实验指导书-实验一-BP算法的MATLAB实现
  10. react做h5 例子_使用React写一个网站的心得体会