首页 > 解决方案 > 8085-进位标志的奇怪行为

问题描述

我正在使用 GNUSim8085 (培训师的结果也相同)

我对指令越来越熟悉,ADC下面的指令似乎没有按我想要的方式工作。

stc  ;to make sure carry is set

mvi a,00h  
mvi b,0ffh          

adc b

hlt

我希望设置进位标志,因为我们要添加 11111111+00000000+00000001 ,所以这显然会产生进位但未设置进位标志。为什么会这样。你能解释一下吗?

还有为什么在下面的代码中而不是在上面的代码中生成进位:

stc  ;to make sure carry is set

mvi a,7dh  ; 7dh  ==    01111101
mvi b,c8h  ; c8h  ==    11001000        

adc b

hlt

标签: assemblysimulator8085

解决方案


继续我之前的评论:这是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_1data + sys.flag.ceef_data_t

如果data == 0xff,则data_1 == 0因为data + sys.flag.c == 0x100,但结果在赋值中被转换回一个 8 位无符号整数,丢失了最高有效位。然后,eef_is_carry用于检查是否有0 + 0xff0 + 0溢出,两者都不是。因此,进位位被清除。但实际的加法当然是 is 0 + 0x100,它肯定会溢出。

我坚持我之前的说法,即这是一个错误。尽管根据公认的长加法规则在数学上应该有进位,但不设置进位标志是不合逻辑的。8085 规范没有描述这种特殊情况。而且,即使例外是有效的,你不同意它应该有充分的记录吗?

最重要的是,这种行为的 ADC 在常见用例中根本无法可靠地工作。硬件级别的 ADC 指令甚至存在的原因是相对于使用比较和分支的丑陋替代方案来提高多字加法的速度(并减少代码大小)。如果 ADC 没有正确检测所有进位条件,则该命令在实现通用多字加法时是不充分的,甚至是无用的。在我看来,与根本没有相比,有一个损坏的 ADC 是没有意义的。(正如我之前所说,由于这个错误,ADC 也违反了交换律a + b == b + a。)

也就是说,您指出您的教练板表现出相同的行为。我没有 8085 教练板,你没有说你有哪一个,所以我无法重现这种行为。我认为您的教练板可能与 GNUSim8085 有相同的错误。根据板上是否有 8085 克隆,这甚至有可能是 GNUSim8085 的“错误兼容错误”的不幸案例。然而,这只是目前的所有猜测。


推荐阅读