8085-进位标志的奇怪行为

时间:2018-06-25 03:06:06

标签: assembly simulator 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

1 个答案:

答案 0 :(得分:3)

继续我先前的评论:这是GNUSim8085源代码的_eef_inst_func_add_with_carry_i中的函数src/8085-instructions.c中的错误。这是master分支off of GitHub中的当前源代码(版本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));

...

请参见lines 326 ff. here

让我们暂时忽略:

  • 冗余分配sys.flag.c = 0;
  • 指向早期与SBB指令有关的错误的注释

该错误是由于eef_data_tguint8的别名,并且代码检查了 是否添加了datadata_1 ,即data + sys.flag.c,转换回eef_data_t,再到累加器,溢出并相应地设置进位标志。

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

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

最重要的是,像这样的ADC根本无法在常见的用例中可靠地工作。甚至在硬件级别上存在ADC指令的原因是,相对于使用比较和分支的丑陋选择,可以提高多字添加的速度(并减小代码大小)。如果ADC无法正确检测所有进位条件,则该命令将不足以实现通用的多字加法。在我看来,与根本没有ADC相比,ADC损坏毫无意义。 (正如我之前所述,由于此错误,ADC还违反了可交换性定律a + b == b + a。)

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