Nand2tetris 中的减法实现

Posted

技术标签:

【中文标题】Nand2tetris 中的减法实现【英文标题】:Subtraction implementation in Nand2tetris 【发布时间】:2019-04-20 10:51:16 【问题描述】:

我目前正在通过 Nand2tetris 为一门大学课程工作,这主要是直截了当的。但是alu可以一步做减法,我完全不明白这是怎么回事。

opMinus = addition <> notX <> notOut

我在网上找不到任何解释。即使 quickcheck 说它是正确的,我自己尝试推导它的最后一步看起来也是无稽之谈:

a - b
a + !b + 1 -- 2s complement
!!(a + !b + 1) -- double negation
!(!a + b) -- apparently this is correct and i have no clue why

最后一步感觉像是依赖于类似的东西

!(a+b) == !a + !b + 1

但我不知道为什么会这样,因此非常感谢您的解释。感谢阅读!

【问题讨论】:

要从 a 中减去 b,更改 b 的符号(翻转位并加 1)并加。 【参考方案1】:

一种更直观而非仅从代数角度看待它的方法是考虑按位补码在整个数轴上的作用,即对称地翻转它。 !a + b 然后在翻转的上下文中添加 b,最后的 ! 将所有内容翻转回来。在翻转的上下文中“向前”步进一个单元(因此,b = 1)在正常上下文中向后退一步,依此类推。

这种“翻转、动作、翻转”有效地将中间的动作从正常工作的方向转向,该原理还有其他实例,有时两个参数都翻转,例如min(a, b) = !max(!a, !b)

【讨论】:

我不明白为什么它会向前迈进,但将!(a+b) 视为-(a+b)-1 回想起来有点明显。【参考方案2】:

对于对此了解较少的人,我没有看到很好的解释,所以我会尽力解释项目书籍告诉你的内容。

由于一些 cpu 实际上有芯片可以接收信号以将加法器切换到减法器(更好的说法实际上是它们的晶体管以允许这样做的方式排列)而 nand2tetris 没有,你实际上必须否定你减去的数字(b)。要在二进制文件中执行此操作,您不是它。如果生活很简单,这将是你的最后一步。

不过,以这个为例。假设你正在编程。您正在使用带符号的 8 位 int 来保存值 b。

这意味着!b = -(b)。所以,如果 b=127,!b = -(127+1) = -128。要更正此问题,您将 添加 1 到 !b 以获得 -127 的正确值。我们现在正处于我们想要减去的正确数字,因此我们可以继续 b 添加到 a(我们要从 减去的数字)。如果 a = 1 且 b = 127,如果我们执行 a + !(b) + 1,结果将是 -126,因为 1 + (-128) + 1 = 2-128 = -126。

另外,请注意,虽然我使用了 !表示NOT,实际的按位运算是~。这被称为 2 的恭维,您可以在此处阅读更多信息:https://en.wikipedia.org/wiki/Two%27s_complement

编辑:删除一个错误。

【讨论】:

【参考方案3】:

在玩了一些之后,我想通了:

(a-b)
!!(a-b)            | double bitwise not is id
!(!(a-b)+1-1)      | +1-1 is id
!(-(a-b)-1)        | !(a-b)+1 = -(a-b)
!(-a + b - 1)      | distribute the negation
!(!a + 1 + b - 1)  | -a = !a+1
!(!a + b)

【讨论】:

是的,陈述(和写下)问题的过程通常是答案的种子。恭喜你解决了!

以上是关于Nand2tetris 中的减法实现的主要内容,如果未能解决你的问题,请参考以下文章

Nand2Tetris C 指令组合中的“a”是啥意思?

VMEmulator Nand2Tetris

Nand2Tetris Hack .asm 汇编代码的时钟和 DFF 示例

预期 Nand2Tetris 跳转指令

尝试为 nand2tetris 构建 PC(计数器),但我在逻辑上遇到了一些问题

nand2tetris 16bit PC 使用 8bit 寄存器