构建一个汇编语言编译器

15

我需要为我构建的CPU架构编写汇编器。该架构类似于MIPS,但这并不重要。

我开始使用C#,尽管C ++更合适。(对我来说C#意味着更快的开发时间)。

我的唯一问题是我无法为此应用程序设计出一个好的设计。我正在构建两遍汇编器。我知道每次传递需要做什么。

我已经实现了第一遍,并且我意识到如果在同一行上有两行汇编代码...不会抛出错误。这意味着只有一种解释:解析技术差。

因此,伟大的程序员们,汇编器之父们,请启迪我如何继续前进。我只需要支持符号和数据声明。指令具有固定大小。

如果需要更多信息,请告诉我。

4个回答

14
我是一个有用的助手,可以为您进行文本翻译。以下是需要翻译的内容:

我已经写了三到四个简单的汇编器。我没有使用解析生成器,而是模拟了我最熟悉的6502 S-C汇编器

为了做到这一点,我使用了一个简单的语法-一行是以下之一:

nothing
[label] [instruction] [comment]
[label] [directive] [comment]

一个标签是一个字母后面跟着任意数量的字母或数字。

一条指令是<空格><助记符> [操作数]

一个指示是<空格>.XX [操作数]

一个注释是*直到行末的内容。

操作数取决于指令和指示。

指示包括

.EQ 定义常量的等同项

.OR 设置代码的起始地址

.HS 字节的十六进制字符串

.AS 字节的ASCII字符串 - 除了空格以外的任何分隔符 - 无论开头是什么,结尾都是它

.TF 输出目标文件

.BS n 保留n个字节的块存储器

我写代码时,为每个组件编写了简单的解析器。每当我遇到一个标签时,我就会将其放入一个表格中,并记录其目标地址。每当我遇到一个未知的标签时,我就会将该指令标记为不完整,并将未知标签与需要修复的指令进行引用。

在所有源代码行都通过之后,我查看“待修复”表并尝试在符号表中找到条目,如果找到,则对指令进行修补。如果没有找到,则会出现错误。

我保留了一个指令名称表和所有操作数的有效寻址模式。当我得到一条指令时,我尝试依次解析每个寻址模式,直到有结果为止。

有了这个结构,整个过程可能需要一两天的时间。


谢谢您的回答。看,我有以下问题:LOOP1: LOOP2: LOOP3:ADD r1,r2 JMP LOOP1按照我编写的汇编程序,它将跳转到包含LOOP2的行,而应该跳转到ADD指令。我正在逐行解析。您是否将整个代码视为单行? - John
你需要将下一个要执行的指令地址作为标签的值存储。这意味着你需要跟踪所有标签,在你的情况下是 Loop(1,2,3),当你到达下一个实际指令(add)时,你就知道标签的值,然后回去填写它们。 - Beardo

5

2

两遍汇编器的第一遍会组装代码并为符号放置占位符(因为在运行汇编器之前你不知道每个东西有多大)。第二遍填写地址。如果组装后的代码需要链接到外部引用,这就是同名链接器的工作。


1

如果你要编写一个汇编器,只需工作并生成一个可加载到微控制器上的十六进制文件,那么它可以简单易用。我的 ciforth 库的一部分是一个完整的 Pentium 汇编器,用于添加内联定义,大约有 150 行。还有一个 8080 的汇编器,只有几十行。

原则解释在 http://home.hccnet.nl/a.w.m.van.der.horst/postitfixup.html。 这相当于将黑板设计模式应用于问题。您首先放置指令,留下任何和所有操作数的空洞。然后,当您遇到参数时,填写这些空洞。
通用工具和指令集之间存在严格的分离。

如果你只是需要自己用的汇编器,并且没有除可用性以外的要求(不是作业),那么你可以在http://home.hccnet.nl/a.w.m.van.der.horst/forthassembler.html中找到一个例子实现。如果你不喜欢Forth,也有Perl的例子实现。如果Pentium指令集太难以理解,你仍然必须能够理解原则和通用部分。 建议先看看asi8080.frt文件。这是389 WOC(代码字数,而不是代码行数)。熟悉指令集的经验丰富的Forth程序员可以在一晚上写出像那样的汇编器。 Pentium很棘手。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接