关于“让我们建立一个编译器”,由Jack Crenshaw撰写

时间:2014-07-30 23:01:16

标签: compiler-construction

(这个问题主要针对那些读过Jack Crenshaw教程的人,但由于这是一个众所周知的教程,我认为这是一个合适的问题。)

我正在阅读Jack Crenshaw撰写的伟大系列节目“Let's Build A Compiler”。

我学到很多,非常享受。但是我在教程中遇到了一些对我没有意义的事情。

在学习如何评估布尔表达式时,给出了以下关于如何组成布尔表达式的“公式”:

<b-expression> ::= <b-term> [<orop> <b-term>]*
<b-term> ::= <not-factor> [AND <not-factor>]*
<not-factor> ::= [NOT] <b-factor>
<b-factor> ::= <b-literal> | <b-variable> | <relation>
<relation> ::= | <expression> [<relop> <expression]
<expression> ::= <term> [<addop> <term>]*
<term> ::= <signed factor> [<mulop> factor]*
<signed factor>::= [<addop>] <factor>
<factor> ::= <integer> | <variable> | (<b-expression>)

为了实现这一点,在解析布尔表达式时,boolExpression函数调用boolTerm函数,该函数调用notFactor函数等...每个函数都保存它的值({ {1}}或1)到寄存器或堆栈上,最终返回0

当我们回到boolExpression时,注册表boolExpression会保留表达式的最终值:D01

据我所知,获取表达式的结果(存储在寄存器0中)之后,需要相应地设置标志(即{{1} - 它设置CPU的标志以表示有关D0)中的值的信息。

这样的控制结构如TST D0可以检查这些标志来决定做什么 - 显然是在评估布尔表达式之后。

但是,出于某种原因,本教程将D0部分放在if函数的末尾,而不是放在TST D0函数的末尾 - 这就是我所在的位置d期待它。

我无法弄明白为什么。

relation比书中多次显示,最后从不与boolExpression一起显示,所以我知道这不是拼写错误或混乱。

我认为boolExpression需要出现在TST D0的末尾,在我们从所有函数返回后,我们在TST D0中得到了表达式的布尔值。然而,在知道boolExpression的最终值之前,作者将此放在D0内,这是一个有时可能在链中间调用的函数。

有人可以向我解释一下吗?为什么要设置标志,即relationD0函数内?为什么不在TST D0

1 个答案:

答案 0 :(得分:0)

克伦肖本人在此解释(强调我的):

  

现在,回想一下我们在寄存器D0中使用零或-1   表示一个布尔值,以及循环结构所期望的值   要设置为对应的标志。在实施所有这一切   68000,事情变得有点棘手。由于循环构造   只在旗帜上操作,它会很好(而且效率很高)   只是设置那些标志,而不是任何东西加载到D0。这个   对于循环和分支会很好,但请记住   可以使用关系任何地方都可以使用布尔因子。我们可能   将其结果存储到布尔变量中。因为我们无法知道   这一点如何使用结果,我们必须允许两种情况   案例。比较数字数据很容易...... 68000有一个   操作...但它设置标志,而不是值。什么&#39; S   更多,标志将始终设置相同(如果相等则为零等),   虽然我们需要为每个设置不同的零标志   不同的重新定位。该解决方案可在68000指令Scc中找到,   它将字节值设置为0000或FFFF(有趣的是如何工作!)   取决于指定条件的结果。如果我们做的   目标字节为D0,我们得到所需的布尔值。   不幸的是,有一个最终的复杂因素:与68000套装中的几乎所有其他指令不同,Scc不会重置条件   用于匹配存储数据的标志。所以我们必须做最后一步,   这是测试D0并设置标志以匹配它。它似乎必须   在月球周围旅行以获得我们想要的东西:我们首先执行   测试,然后测试标志将数据设置为D0,然后测试D0设置   再次举旗帜。它有点迂回,但它是最多的   让旗帜正确的直接方式,毕竟它只是一个   几个指示。

(摘自here