继续我之前的评论:这是GNUSim8085 源代码中的函数_eef_inst_func_add_with_carry_i
中的一个错误。这是来自GitHub的分支src/8085-instructions.c
的当前源代码(rev. 88a604043a2b7f153ff97e2c3026145814f7fc39):master
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));
…</p>
见第 326 行以下。在这里。
我们暂时忽略:
- 冗余分配
sys.flag.c = 0;
- 指向与 SBB 指令相关的早期错误的注释
该错误是由于eef_data_t
是 的别名guint8
,并且代码检查是否添加或,即data
转换回累加器,溢出并相应地设置进位标志。data_1
data + sys.flag.c
eef_data_t
如果data == 0xff
,则data_1 == 0
因为data + sys.flag.c == 0x100
,但结果在赋值中被转换回一个 8 位无符号整数,丢失了最高有效位。然后,eef_is_carry
用于检查是否有0 + 0xff
或0 + 0
溢出,两者都不是。因此,进位位被清除。但实际的加法当然是 is 0 + 0x100
,它肯定会溢出。
我坚持我之前的说法,即这是一个错误。尽管根据公认的长加法规则在数学上应该有进位,但不设置进位标志是不合逻辑的。8085 规范没有描述这种特殊情况。而且,即使例外是有效的,你不同意它应该有充分的记录吗?
最重要的是,这种行为的 ADC 在常见用例中根本无法可靠地工作。硬件级别的 ADC 指令甚至存在的原因是相对于使用比较和分支的丑陋替代方案来提高多字加法的速度(并减少代码大小)。如果 ADC 没有正确检测所有进位条件,则该命令在实现通用多字加法时是不充分的,甚至是无用的。在我看来,与根本没有相比,有一个损坏的 ADC 是没有意义的。(正如我之前所说,由于这个错误,ADC 也违反了交换律a + b == b + a
。)
也就是说,您指出您的教练板表现出相同的行为。我没有 8085 教练板,你没有说你有哪一个,所以我无法重现这种行为。我认为您的教练板可能与 GNUSim8085 有相同的错误。根据板上是否有 8085 克隆,这甚至有可能是 GNUSim8085 的“错误兼容错误”的不幸案例。然而,这只是目前的所有猜测。