继续我之前的评论:这是函数中的一个错误_eef_inst_func_add_with_carry_i
in src/8085-instructions.c
GNUSim8085 源代码。这是当前的源代码master
分支,离开 GitHub https://github.com/GNUSim8085/GNUSim8085(修订版 88a604043a2b7f153ff97e2c3026145814f7fc39):
eef_data_t data_1;
/* I'm not sure abt the new code
* Old code:
if (op == '+')
data_1 = data + sys.flag.c;
else
data_1 = data - sys.flag.c;
*/
data_1 = data + sys.flag.c;
/* check for flags */
sys.flag.c = 0;
sys.flag.c = (_eef_is_carry (sys.reg.a, data, op)
|| _eef_is_carry (sys.reg.a, data_1, op));
…
See 第 326 行以下这里 https://github.com/GNUSim8085/GNUSim8085/blob/ebbda5941092781acf1f60dd1c2b95828cbf3d2e/src/8085-instructions.c.
我们暂时忽略:
- 冗余分配
sys.flag.c = 0;
- 指向与 SBB 指令相关的早期错误的评论
该错误是由于eef_data_t
是 的别名guint8
,以及检查是否的代码either添加data
or data_1
,即data + sys.flag.c
,转换回eef_data_t
,累加器溢出,并相应地设置进位标志。
If data == 0xff
, then data_1 == 0
因为data + sys.flag.c == 0x100
,但结果会在赋值中转换回 8 位无符号整数,丢失最高有效位。然后,eef_is_carry
用于检查是否0 + 0xff
, or 0 + 0
溢出,两者都不是这种情况。因此,进位位被清除。但实际的添加当然是0 + 0x100
,这肯定会溢出。
我坚持之前的说法,即这是一个错误。尽管根据公认的长加法规则,在数学上应该存在进位,但不设置进位标志是不合逻辑的。 8085 规范没有描述这种特殊情况。而且,即使例外是有效的,您是否同意应该对其进行详细记录?
最重要的是,像这样的 ADC 在常见用例中根本无法可靠地工作。硬件级 ADC 指令存在的原因是相对于使用比较和分支的丑陋替代方案,提高多字加法的速度(并减少代码大小)。如果 ADC 没有正确检测到所有进位条件,则该命令在实现通用多字加法时是不够的,甚至是无用的。在我看来,拥有一个损坏的 ADC 与根本没有 ADC 相比毫无意义。 (正如我之前所说,由于这个错误,ADC 也违反了交换律a + b == b + a
.)
也就是说,您指出您的培训板也表现出相同的行为。我没有 8085 训练板,而且你也没有说你有哪一个,所以我无法重现这种行为。我认为你的训练板可能有与 GNUSim8085 相同的错误。根据板上是否有 8085 克隆,这甚至可能是 GNUSim8085 的“bug for bug 兼容性”的不幸情况。然而,这只是目前的所有猜测。