目标:我想编写一个X86_64汇编程序。注:标记为社区wiki
背景:我熟悉C。我以前写过MIPS程序集。我编写了一些x86程序集。但是,我想编写一个x86_64汇编程序--它应该输出我可以跳到并开始执行的机器代码(就像在JIT中那样)。
问题是:解决这个问题的最好方法是什么?我意识到这个问题看起来很大。我想从一套基本的最低标准开始:
只是一个基本的集合,使它完成图灵。有人做过这个吗?建议/资源?
发布于 2010-06-19 01:52:54
像任何其他“编译器”一样,汇编程序最好写成一个词汇分析器,输入到语言语法处理器中。
与常规编译语言相比,汇编语言通常更容易,因为您不需要担心跨越线边界的构造,格式通常是固定的。
大约两年前,为了教育目的,我为一个(虚构的) CPU编写了一个汇编程序,它基本上将每一行处理为:
:loop)。mov)。ax,$1)。最简单的方法是确保令牌易于区分。
这就是为什么我制定了标签必须从:开始的规则--它使得对这一行的分析变得非常容易。处理线路的过程是:
; )。您可以很容易地坚持不同的操作数也有特殊的标记,以使您的生活更轻松。所有这些都是假设您可以控制输入格式。如果你需要使用英特尔或AT&T格式,那就有点困难了。
我处理它的方式是,有一个简单的每个操作函数被调用(例如,doJmp、doCall、doRet),该函数决定了操作数中允许的内容。
例如,doCall只允许一个数字或标签,而doRet不允许任何东西。
例如,下面是来自encInstr函数的代码段:
private static MultiRet encInstr(
boolean ignoreVars,
String opcode,
String operands)
{
if (opcode.length() == 0) return hlprNone(ignoreVars);
if (opcode.equals("defb")) return hlprByte(ignoreVars,operands);
if (opcode.equals("defbr")) return hlprByteR(ignoreVars,operands);
if (opcode.equals("defs")) return hlprString(ignoreVars,operands);
if (opcode.equals("defw")) return hlprWord(ignoreVars,operands);
if (opcode.equals("defwr")) return hlprWordR(ignoreVars,operands);
if (opcode.equals("equ")) return hlprNone(ignoreVars);
if (opcode.equals("org")) return hlprNone(ignoreVars);
if (opcode.equals("adc")) return hlprTwoReg(ignoreVars,0x0a,operands);
if (opcode.equals("add")) return hlprTwoReg(ignoreVars,0x09,operands);
if (opcode.equals("and")) return hlprTwoReg(ignoreVars,0x0d,operands);hlpr...函数只接受操作数,并返回一个包含指令的字节数组。当许多操作有类似的操作数要求时,例如adc、,、add、and和`所有在上述情况下都需要两个寄存器操作数(第二个参数控制指令返回的操作码)时,它们非常有用。
通过使操作数的类型易于区分,您可以检查提供了哪些操作数,它们是否合法,以及要生成哪些字节序列。将操作分离成它们自己的功能提供了一个良好的逻辑结构。
此外,大多数CPU遵循从操作代码到操作的合理逻辑转换(以使芯片设计人员更容易使用),因此对于所有允许索引寻址的操作码,都会有非常类似的计算。
为了在CPU中正确地创建允许可变长度指令的代码,最好在两次传递中完成。
在第一遍中,不要生成代码,只需要生成指令的长度。这允许您在遇到所有标签时为它们赋值。第二次传递将生成代码,并可以填充对这些标签的引用,因为它们的值是已知的。上面那个代码段中的ignoreVars就是为此目的使用的(返回了字节代码序列,这样我们就可以知道长度,但是任何对符号的引用都只是使用0)。
发布于 2010-06-19 02:49:42
这并不是为了让你气馁,但是已经有了各种不同的许多汇编程序。请考虑为现有的开源项目(如elftoolchain工具链 )做出贡献。
https://stackoverflow.com/questions/3074004
复制相似问题