haskell中的CPU仿真,功能数据结构,还是拉链?

时间:2013-05-29 01:38:47

标签: haskell functional-programming

嗯,不完全是。我有更多的功能数据结构问题。

说我想模拟CPU的执行。我有一些改变CPU状态的指令(比如它是基于堆栈的cpu。只有跳转有操作数......或者其他),组成程序的一些指令列表和标签。通过引用某些标签来完成跳转,而不是某些偏移。我该如何表达这个?

如果我的程序看起来像[Label "foo", Add, Add, Mult, Label "bar", Jnz "foo"],那么当我点击Jnz "foo"时,我需要向后和向前搜索标签“foo”以继续执行。这看起来有点傻。我想我应该能够拥有一个更好的数据结构,允许快速跳转到标签。现在,任意我会说我不想存储偏移量。假设CPU允许自我修改代码或类似的东西。我应该如何修补代码,同时确保引用仍然指向当前版本的代码?

我喜欢拉链的想法。 我只是不知道在O(1)时间内拉链跳转到预定义位置的想法是否有意义

2 个答案:

答案 0 :(得分:2)

答案(但我不确定它是你想要的)是做LLVM的工作并将代码存储为BasicBlock。在这个系统中,每个块都是一段只能从头开始输入的代码。最后一条指令必须跳转到另一个块。然后,您的标签将附加到基本块,而不是在指令列表中。程序可能如下:

newtype Lable = [Char]
data Code = Data.Map Label [Instruction]

当你点击跳转指令时,你只需lookup它在地图中的阻挡并继续前进。

如果您的目标是优化代码(这也是LLVM使用它的原因),这有一些真正的优势,但它确实打破了将代码简单地表示为指令列表的模式。

另一方面,我无法想到程序代码中包含标签的任何CPU或计算模型。在汇编中,它们只是描述下一行代码的固定偏移量的便捷方式。它们不会在输出中结束,如果代码在运行时可修改,则jmp指令也需要修改。

答案 1 :(得分:1)

我建议像

import Data.Map as M
data Code = Code { instructions :: [Instruction], labels :: M.Map String [Instruction] }

其中标签映射的值与指令列表共享。您可以将标签保留在指令流中并执行类似

的操作
mkCode is = Code is (scan is)
              where scan [] = M.empty
                    scan (Label l:js) = M.insert l js (scan js)
                    scan (_:js) = (scan js)

建立正确的代码值。

请注意Data.Map实现二叉搜索树。如果你想要哈希表Data.Hashtable