2

我正在为特定指令集编写汇编程序。我坚持的阶段是我正在使用 switch case 将指令转换为它们各自的十六进制代码。因此,对于 25 条指令,我使用了 25 种情况,我的代码可以转换指令。有没有更好的方法来转换这些指令,而不是使用这么多开关案例。ISA 可以在这里找到:https ://docs.google.com/file/d/1uIzgSaTD-onlr6f3ltmZkGRuYpAxIKqKSvOSAYsjREeBawYD7vRE4q42i9dM/edit?usp=sharing

4

3 回答 3

4

当我编写汇编程序时,我有几个字典,它们为每条指令存储了它们的编码和调用执行它的回调(那是 C#,你不介意吗?;)):

class Processor {
    static Dictionary<string, int> _encodings = new Dictionary<string, int>() {

        { "mov", 0x00000032 },
        { "add", 0x00000051 }
        // etc.
    };

    static Dictionary<string, Action<object, object>> _callbacks = 
        new Dictionary<string, Action<object, object>>() {

            { "mov", executeMov },
            { "add", executeAdd } 
            // ect
    };

    void executeMov(object o1, object o2) {
        // ...
    }

    void executeAdd(objecy o1, object o2) {
        // ...
    }
}
于 2013-03-03T09:19:54.163 回答
2

我会创建一组描述每条指令的结构。该结构将包含:

  • 指令助记符(例如"AND"
  • 指令操作码(例如0
  • 指令操作数类型(例如no operand, register operand, memory operand, immediate operand, 2 register operands, register operand + memory operand, register operand + immediate operand, memory operand + immediate operand, 等)

然后您可以通过助记符搜索数组并查看该指令接受哪些操作数并将其与输入程序集的操作数匹配。如果没有匹配,您检查是否有另一个版本的相同指令和相同的助记符但具有不同的操作数和重复匹配(看起来AND有两种口味)。如果整个数组中没有匹配项,则会失败并出现错误。

简单、通用、可扩展。除非有性能要求,否则我不会费心优化速度。

于 2013-03-03T11:06:07.433 回答
0

在某些时候,您将获得枚举所有指令的复杂性。但我很无聊,所以这里有一种将复杂性移开的方法是做这样的事情,伪代码:

 abstract class InstructionWriter
      void writeInstruction(file, data)

 ...lots of different instruction writers...


 void setupWriters() {
      writers = Container<InstructionWriter>(NUM_OP_CODES);
      writers[OPCODE1] = writerForOpCode1();
      writers[OPCODE2] = writerForOpCode2();
      ...
 }

那么实际的写作可以重写为

 void writeInstructions(program) {
     file = open(binaryfile)
     for(opcode o in program) {
         writers[o.opcode].write(file, o.data);
     }
 }

尽管通过定位所有继承的函数等,这种方法可能会比 switch 慢,但这只是一个猜测。

于 2013-03-03T09:20:13.280 回答