首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何编写X86_64 _assembler_?

如何编写X86_64 _assembler_?
EN

Stack Overflow用户
提问于 2010-06-19 01:43:23
回答 2查看 1.1K关注 0票数 6

目标:我想编写一个X86_64汇编程序。注:标记为社区wiki

背景:我熟悉C。我以前写过MIPS程序集。我编写了一些x86程序集。但是,我想编写一个x86_64汇编程序--它应该输出我可以跳到并开始执行的机器代码(就像在JIT中那样)。

问题是:解决这个问题的最好方法是什么?我意识到这个问题看起来很大。我想从一套基本的最低标准开始:

  • 装入寄存器
  • 寄存器上的运算量(只是整数很好,还没有必要弄乱FPU )
  • 条件词
  • 跳跃

只是一个基本的集合,使它完成图灵。有人做过这个吗?建议/资源?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-06-19 01:52:54

像任何其他“编译器”一样,汇编程序最好写成一个词汇分析器,输入到语言语法处理器中。

与常规编译语言相比,汇编语言通常更容易,因为您不需要担心跨越线边界的构造,格式通常是固定的。

大约两年前,为了教育目的,我为一个(虚构的) CPU编写了一个汇编程序,它基本上将每一行处理为:

  • 可选标签(例如,:loop)。
  • 操作(如mov)。
  • 操作数(例如,ax,$1)。

最简单的方法是确保令牌易于区分。

这就是为什么我制定了标签必须从:开始的规则--它使得对这一行的分析变得非常容易。处理线路的过程是:

  • 去掉注释(从字符串到行尾的第一个; )。
  • 如果存在,请提取标签。
  • 第一个词是操作。
  • 休息是操作数。

您可以很容易地坚持不同的操作数也有特殊的标记,以使您的生活更轻松。所有这些都是假设您可以控制输入格式。如果你需要使用英特尔或AT&T格式,那就有点困难了。

我处理它的方式是,有一个简单的每个操作函数被调用(例如,doJmpdoCalldoRet),该函数决定了操作数中允许的内容。

例如,doCall只允许一个数字或标签,而doRet不允许任何东西。

例如,下面是来自encInstr函数的代码段:

代码语言:javascript
复制
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)。

票数 8
EN

Stack Overflow用户

发布于 2010-06-19 02:49:42

这并不是为了让你气馁,但是已经有了各种不同的许多汇编程序。请考虑为现有的开源项目(如elftoolchain工具链 )做出贡献。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3074004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档