(这个问题主要针对那些读过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
会保留表达式的最终值:D0
或1
。
据我所知,在获取表达式的结果(存储在寄存器0
中)之后,需要相应地设置标志(即{{1} - 它设置CPU的标志以表示有关D0
)中的值的信息。
这样的控制结构如TST D0
可以检查这些标志来决定做什么 - 显然是在评估布尔表达式之后。
但是,出于某种原因,本教程将D0
部分放在if
函数的末尾,而不是放在TST D0
函数的末尾 - 这就是我所在的位置d期待它。
我无法弄明白为什么。
relation
比书中多次显示,最后从不与boolExpression
一起显示,所以我知道这不是拼写错误或混乱。
我认为boolExpression
需要出现在TST D0
的末尾,在我们从所有函数返回后,我们在TST D0
中得到了表达式的布尔值。然而,在知道boolExpression
的最终值之前,作者将此放在D0
内,这是一个有时可能在链中间调用的函数。
有人可以向我解释一下吗?为什么要设置标志,即relation
在D0
函数内?为什么不在TST D0
?
答案 0 :(得分:0)
克伦肖本人在此解释(强调我的):
现在,回想一下我们在寄存器D0中使用零或-1 表示一个布尔值,以及循环结构所期望的值 要设置为对应的标志。在实施所有这一切 68000,事情变得有点棘手。由于循环构造 只在旗帜上操作,它会很好(而且效率很高) 只是设置那些标志,而不是任何东西加载到D0。这个 对于循环和分支会很好,但请记住 可以使用关系任何地方都可以使用布尔因子。我们可能 将其结果存储到布尔变量中。因为我们无法知道 这一点如何使用结果,我们必须允许两种情况 案例。比较数字数据很容易...... 68000有一个 操作...但它设置标志,而不是值。什么&#39; S 更多,标志将始终设置相同(如果相等则为零等), 虽然我们需要为每个设置不同的零标志 不同的重新定位。该解决方案可在68000指令Scc中找到, 它将字节值设置为0000或FFFF(有趣的是如何工作!) 取决于指定条件的结果。如果我们做的 目标字节为D0,我们得到所需的布尔值。 不幸的是,有一个最终的复杂因素:与68000套装中的几乎所有其他指令不同,Scc不会重置条件 用于匹配存储数据的标志。所以我们必须做最后一步, 这是测试D0并设置标志以匹配它。它似乎必须 在月球周围旅行以获得我们想要的东西:我们首先执行 测试,然后测试标志将数据设置为D0,然后测试D0设置 再次举旗帜。它有点迂回,但它是最多的 让旗帜正确的直接方式,毕竟它只是一个 几个指示。
(摘自here)