5

我有三个问题:

  1. 我可以使用什么编译器以及如何使用它将 C 源代码编译成机器代码
  2. 我可以使用什么汇编程序以及如何使用它将 ASM 汇编为机器代码
  3. (可选)您如何建议将机器代码放置在正确的地址中(即引导加载程序机器代码必须放置在引导扇区中)?

我的目标: 我正在尝试制作一个基本的操作系统。这将使用个人制作的引导加载程序和内核。我也会尝试从 Linux 内核(即驱动程序)中获取一些零碎的东西并将它们集成到我的内核中。我希望在大多数现代计算机上创建一个类似 DOS 的 32 位操作系统来处理内存问题。我认为我不会为我的操作系统创建可执行格式,因为我的操作系统不会动态到需要它。

我的情况: 我在带有 Intel Celeron CPU 的 x86-64 windows 8 笔记本电脑上运行;我相信它使用安全启动。我将在带有 Intel Core I3 CPU 的 x86-64 桌面上测试我的操作系统。我对操作系统及其技术有一个平均的了解。我知道这个项目所需的 C、ASM 和计算机理论。我认为还值得注意的是,我 16 岁,没有受过正规的计算机科学教育。

我的研究:在谷歌搜索 C 通常编译成什么后,我找到了各种答案,包括机器代码、二进制、普通二进制、原始二进制、汇编和可重定位目标代码。据我了解,程序集通常会组装成 PE 格式的可执行文件。我听说过 Cygwin、GCC C 和 MingW C 编译器。至于汇编器,我听说过 FASM、MASM 和 NASM。我搜索过OSDevOSDever等网站。

我尝试过的:我尝试设置 GCC(一场噩梦)并创建一个交叉编译器(另一个噩梦)。

结论:如您所知,我对编译器、汇编器和可执行格式感到困惑。请在回答我的问题的同时消除我的无知。这些可能是唯一让我无法在简历中使用操作系统的事情。抱歉,我会包含更多链接,但 stackoverflow 不会让我制作两个以上的链接。万分感谢!

4

4 回答 4

5

首先,快速回答您的三个问题。

  1. 几乎任何编译器都会将 C 代码翻译成汇编代码。这就是编译器所做的。GCC 和 clang 很受欢迎并且是免费的。

    clang -S -o example.s example.c
    
  2. 您选择的任何编译器都可能支持汇编,只需使用相同的编译器驱动程序即可。

    clang -o example.o example.s
    
  3. 您的链接器文档将告诉您如何将特定代码放在特定地址等等。如果您如上所述使用 GCC 或 clang,您可能会使用ld(1). 在这种情况下,请阅读“链接器脚本”。

接下来,一些注意事项:

  • 您不需要交叉编译器或自行设置 GCC。您正在使用 Intel 机器,为 Intel 机器生成代码。linux 发行版附带的任何 clang 或 GCC 二进制发行版都应该可以正常工作。

  • C 编译器通常将代码编译成程序集,然后将生成的程序集传递给系统汇编器以得到机器代码。机器码、二进制、普通二进制、原始二进制基本上都是同义词。

  • 生成的机器代码被打包成某种可执行文件格式,告诉主机操作系统如何加载和运行代码。在 Windows 上是 PE,在 Linux 上是 ELF,在 Mac OS X 上是 Mach-O。

  • 您不需要为您的操作系统创建可执行格式,但您可能想要使用一种。ELF 是一个非常简单(并且有据可查)的选项。

还有一点个人注意事项,我希望不会让您太沮丧 - 如果您对编译器、汇编器、链接器和所有这些工具的工作方式不是熟悉,那么您的项目将非常困难和混乱。可以这么说,您可能想从一些较小的项目开始以获得您的“海腿”。

于 2013-02-02T21:06:00.947 回答
2

我想你的问题的第一部分已经回答了,所以我将讨论另外两个:

我可以使用什么汇编程序以及如何使用它将 ASM 汇编为机器代码?

, (基本上非常喜欢), , "masm" ie 之一,nasm并且作为 Microsoft 工具的一部分免费提供。yasmnasmfasmml64.exeml.exe

其中,我可能会推荐nasmyasm。该建议完全基于个人喜好 - 但他们支持的广泛平台以及默认使用英特尔语法是我的原因。我会尝试一些,看看你喜欢什么。

(可选)您如何建议将机器代码放置在正确的地址中(即引导加载程序机器代码必须放置在引导扇区中)?

好吧,只有一种方法可以将引导加载程序放置在 MBR 的正确地址 - 打开 LBA 0 处的磁盘并在那里准确写入 512 个字节,以0x55AA. 冲洗,然后关闭。MBR 通常还包含一个嵌入其中的分区表——它既是代码又是数据。这个东西的科学术语是冯诺依曼架构,可以简单概括为“程序和数据存储在同一个地方”。BIOS 想要从磁盘启动时的操作是将前 512 个字节读入内存,检查签名,如果匹配,则执行该内存(从字节 0 开始)。

好的,这些问题就不用说了。现在我再给你一些注意事项:

  • 引导加载程序的 512 字节对于任何人来说都不够用。因此,一些文件系统包含引导扇区,引导加载程序本身只是加载在这些扇区中找到的代码/数据。这允许加载更大量的代码——足以让内核运行。例如,grub 在旧版本中包含 stage1、stage1_5 和 stage2 组件。
  • 尽管大多数操作系统都要求您使用可执行格式容器,但您并不需要。在磁盘和内存中,可执行代码只是一个、两个或三个字节的字符串,称为操作码。您可以阅读操作码参考或 Intel/AMD 手册以了解十六进制值转换为什么。无论如何,您可以使用 nasm 执行从汇编程序到二进制文件的直接转换,如下所示:

     nasm -f bin input.asm -o output.asm
    

    尽管结果可能不会执行,但它非常适用于 16、32 或 64 位汇编程序。唯一的地方是,如果您[bits 16]在代码中显式使用该指令以及org 100h,那么您将拥有一个 MSDOS .com 程序。不幸的是,这是现有的最简单的二进制格式——你只有一大块代码和数据,而且不能超过单个段的大小。

    我觉得这可能会解决这一点:

    我找到了各种答案,包括机器代码、二进制、普通二进制、原始二进制、汇编和可重定位目标代码。

    关于汇编组装成什么的答案 - 它组装成操作码和内存地址,具体取决于汇编程序。这以字节表示,这些字节本身就是数据。您可以使用十六进制编辑器原始阅读它们,尽管在少数情况下这是绝对必要的。我提到内存地址是因为一些操作码控制如何解释内存地址 - 例如,可重定位目标代码要求地址不是硬编码的(相反,它们被解释为与当前位置的偏移量)。

    据我了解,程序集通常会组装成 PE 格式的可执行文件。

    可以公平地说,派生出 C/C++ 的汇编器被编译为操作码,然后这些操作码与程序中包含的任何其他内容(数据、资源)一起以可执行格式(例如 PE)存储。通常取决于您的操作系统。

  • 如果你彻底阅读了 OSDev Wiki,你会意识到分段寻址是一件非常痛苦的事情——现代操作系统中段的标准和唯一用法是定义跨越整个地址空间的四个段——在环 0 和 3 处的两个数据段,在环 0 和 3 的两个代码段。

  • 如果您还没有彻底阅读OSDEV Wiki,那么您应该阅读。我还推荐JamesM 的内核教程,其中包含有关在 C 中构建内核的实用建议。

  • 如果你只是想对一个 DOS 内核做坏事,你实际上仍然可以不需要自己编写一个完整的内核。您还应该能够将 CPU 从 DOS 切换到保护模式。您需要FreeDOS和您选择的汇编程序。有一个关于终止和保持驻留的优秀教程,这基本上意味着挂钩一个中断例程,然后将自己从活动进程列表中编辑出来,在Rootkit 兵工厂。互联网上可能也有这方面的教程。

    我可能很想建议首先这样做,只是为了让自己习惯这种低级的东西。

  • 如果你只是想戳一个操作系统,你可以在 Windows 上设置内核调试。WinDbg 有点……晦涩难懂,但一旦你习惯了它就会变得有意义。
  • 您提到您的笔记本电脑使用安全启动。如果是这种情况,您的笔记本电脑使用 UEFI。如果您想阅读此内容,UEFI 规范100% 保证比您的数学作业更无聊,但我建议您略读它以了解目标和基本环境。重要的是拥有EFI SDK,它使您能够构建与 EFI 兼容的应用程序(PE 格式并存在于磁盘上的 FAT32 分区上 - 因此安装 EFI 引导加载程序非常简单,即使编写一个不是这样。如果我必须提出一个诚实的建议,我现在会坚持使用 MBR,因为在撰写本文时使用 MBR 模拟操作系统比 EFI 容易得多,而且您现在确实想在某种形式的 VM 中执行此操作. 另外,我会使用现有的 grub,因为引导加载程序并不是那么令人兴奋,真的。
  • 别人说了,我就说:你绝对想在某种形式的模拟器或虚拟机下做这样的事情。你肯定会犯错,而且你会遇到你不理解的事情。模拟器和虚拟机软件现在是免费的,有些像 BOCHS 会告诉你给定故障、陷阱等的原因是什么。这很有帮助!
于 2013-02-02T22:45:49.043 回答
2

起初,“机器码”和“二进制”是同义词。“目标代码”是某种中间形式,链接器将在最后转换为二进制。一些 C/C++ 编译器不是直接生成二进制文件,而是生成汇编程序源代码,它们提供给汇编程序,生成目标代码,然后提供给链接器,生成最终的二进制文件。在大多数情况下,这些过程对用户是透明的。您向编译器提供 C/C++/Pascal/任何源代码,并在输出中获得一个二进制文件。

FASM 汇编器,又名 flatassembler是 OS 开发的最佳汇编器。FASM 中已经创建了几个操作系统。

那是因为 FASM 是可自编译的并且非常易于移植。这样,在 2..3 天内,您可以将它移植到您的操作系统,然后您的操作系统将变得自给自足 - 即您将能够从您的操作系统中编译程序。

FASM 的另一个优点是它不需要链接器——它可以直接生成多种格式的二进制文件。

活跃的大社区也很重要。有大量可用于 FASM 的资源,包括用于操作系统开发的资源。

留言板非常活跃,是可以学到很多东西的地方。

于 2013-02-02T22:02:23.243 回答
0

首先,使用 Virtual box 之类的东西进行测试

我认为您可能想要采取一些较小的步骤,以便轻松编写 C 代码。

然后看看磁盘上的引导扇区是如何工作的(在互联网上有很好的记录)还看看其他开源引导加载程序的代码。

然后看看怎么做任务切换。写起来也不难。您甚至可以在尝试嵌入到您自己的操作系统之前在您的正常操作系统下运行它的大部分内容

使用 C 编译器,您通常可以将 asm inline 通常与asm { /* assembly code */ }

于 2013-02-02T21:09:11.477 回答