Electronic Joint Business

Solution for E-Business

binutils

操作系统开发初体验 (1)

文章评价:
如果你正在读这篇文章,没准你想知道更多有关如何创建自己的 OS 方面的内容。不过你首先要知道,我这短短几篇文章是没办法涵盖 OS 开发的各个方面的。我会介绍一些 OS 的基础知识,但还需要靠你自己去研读相关的技术文档,这样你才能明白操作系统为何如此工作。确定还想读下去吗?好,让我们开始吧。

理解 OS 开发很关键的一点是:一切将从零开始,你直接和硬件打交道。你会遇到硬件故障,也不能指望系统每次都如期工作。你没有标准库可供使用,更没有 .NET 框架或者Java 虚拟机。一切只能靠你自己。

开始之前,你要了解系统控制权是如何转交到你手上的。很奇怪的是,没有什么标准规定电脑开机之后应置于什么状态,唯一能确定的是,开机之后一定会去执行引导扇区,它位于可启动的存储介质的起始部分,会被加载到内存地址 0x7C00 处,其长度为 512字节,并以 0xAA55 作为文件末尾签名。引导扇区通常用汇编语言编写。为了节约时间,我们将使用现成的 GRUB (Grand Unified Bootloader)。这可为后续工作提供可靠的基础,并将电脑置于同一个标准状态。

Grub 会将电脑置于以下状态:

  • 保护模式
  • A20 地址线启用
  • 寄存器 EBX 存有指向多重启动信息结构(Multiboot information structure)的指针
  • 寄存器 EAX 存有固定值 0x2BADB002
  • 分页机制关闭
  • 栈位于内存的某处
  • 中断机制关闭

下面我会逐一介绍这些状态。保护模式允许内核开发人员按虚拟地址空间访问最大为 4GB 的内存,并引入了保护环“Ring”的概念。以下几小节会介绍更多的内容。 A20 门电路是键盘控制器附近的一条“古老”的地址线。它最初设计是为了与 8086 保持兼容,在“关闭”的时候,屏蔽了对内存开始部分 1M 以上地址的访问。

>>> 阅读全文

 

, , , , , , , ,

GCC 4.6.0 编译优化选项

应该谨记在心的是,:“使用编译器优化得到的小幅度性能提升,与它带来的风险相比微不足道” — 源自 LFS-Book.

追求极致的优化是一件既耗时又麻烦的事情,你会陷入无止尽的测试、测试、再测试…所以优化应当适可而止为好,将精力留出来用在程序算法的优化上会有更有意义。此本文的主旨是针对 GCC 4.6.0 的优化选项给出一个完整和清晰的脉络,仅仅作为参考。

GCC 编译的基本过程
在 Unix 环境下(包括 Unix、Linux、MSYS 和 Cygwin 等等),软件源代码大多提供了 configure 脚本,该脚本一般都会有许多配置选项,其中有不少选项是与性能息息相关的。对于每个特定的软件包,在编译前应该使用 configure –help 查看所有选项,并精心选择有关选项。运行 configure 脚本后会生成有关项目的 Makefile。将源代码编译为二进制文件是在 Makefile 文件的指导下,由 make 程序调用一条条编译命令完成的。而将源代码编译为二进制文件又需要经过以下四个步骤:预处理(cpp) → 编译(gcc或g++) → 汇编(as) → 连接(ld) ;括号中表示每个阶段所使用的程序,它们分别属于 GCC 和 Binutils 软件包。

尽管将源代码编译为二进制文件的四个步骤由不同的程序( cpp,gcc/g++,as,ld)完成,但是事实上 cpp, as, ld 都是由 gcc/g++ 进行间接调用的。换句话说,控制了 gcc/g++ 就等于控制了所有四个步骤。

显然的,优化应当从编译工具自身的选择以及控制编译工具的行为入手。本文以 Binutils-2.21.1 和 GCC-4.6.1为例进行说明。

>>> 阅读全文

 

,

Gnu Binutils 命令小结

我们知道, gcc(gnu collect compiler)是一组编译工具的总称,包括c,c++等等,它主要完成的工作任务是“预处理”和“编译”,以及提供了与编译器紧密相关的运行库的支持,如libgcc_s.so、libstdc++.so等。

而binutils提供了一系列用来创建、管理和维护二进制目标文件的工具程序,binutils与gcc是紧密相集成的,没有binutils的话,gcc是不能正常工作的。 Binutils提供了一下的工具,主要有:
addr2line 把程序地址转换为文件名和行号。在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出在给出的地址上是哪个文件以及行号。

ar建立、修改、提取归档文件。归档文件是包含多个文件内容的一个大文件,其结构保证了可以恢复原始文件内容。

as主要用来编译GNU C编译器gcc输出的汇编文件,产生的目标文件由连接器ld连接。

c++filt 连接器使用它来过滤 C++ 和 Java 符号,防止重载函数冲突。

>>> 阅读全文

 

, ,

从MinGW交叉编译出MinGW64

MinGW一直没有推出64位的版本,因此在SF.NET上又有一个新的项目叫 MinGW64,虽然大家支持的都是 GCC,但是两个项目是有一些区别的,除了前面提及的32位版和64位版的问题外,主要是二者的运行时不尽相同,MinGW64 重写了自己的 MinGW 运行时,称为 MinGW-W64,和 MinGW 相比,其运行时支持的 Windows API 更多一些。

但是 MinGW64 上发布的二进制包中,缺少一些很有意思的语言工具,比如 ada。而编译ada要求GCC中一定要有 gnat(即 ada 编译器)存在,而目前只有 MinGW 才提供了 ADA 编译器,所以我们必须回到起点,从32位的 MinGW 逐步交叉编译 MinGW64。

这个过程会用到的工具有:MinGW 和 MSYS 的二进制包和以下源代码包,包括:binutils (2.22), GCC (4.7.0),MinGW-W64运行时(2.0.2), gmp (5.0.1), mpfr (3.1.0), MPC (0.9)。 要求 MinGW 中 GCC 工具的版本,最好要编译的源代码一直,避免出现低版本的 GNAT 无法识别高版本的 ADA 语法而报错。

一切就绪之后,可以开始解压源代码包,并将 gmp,mpfr 和 mpc 拷贝到 gcc-4.7.0 的目录中,并去掉名字中的版本号。 我们下来首先会构造出交叉编译的工具来。

创建32位交叉编译环境
1. 创建临时工作目录
我们的32位交叉编译环境将要被发布到 C:\\tools 目录下,打开DOS窗口,创建一个文件夹 tools。之后在 MSYS 安装目录下找到 etc 文件夹里的 fstab 文件,添加一行:

>>> 阅读全文

 

, , , ,