我正在使用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
答案 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));
...
让我们暂时忽略:
sys.flag.c = 0;
该错误是由于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
是否溢出,都不是这种情况。因此,进位位被清除。但是,实际的加成当然是0 + 0x100
,肯定会溢出。
我坚持我先前的说法,这是一个错误。尽管根据公认的长加法则,在数学上应该有一个进位,但将进位标志置为不逻辑是不合逻辑的。 8085规范没有描述这种特殊情况。而且,即使该例外有效,您是否也同意将其记录在案?
最重要的是,像这样的ADC根本无法在常见的用例中可靠地工作。甚至在硬件级别上存在ADC指令的原因是,相对于使用比较和分支的丑陋选择,可以提高多字添加的速度(并减小代码大小)。如果ADC无法正确检测所有进位条件,则该命令将不足以实现通用的多字加法。在我看来,与根本没有ADC相比,ADC损坏毫无意义。 (正如我之前所述,由于此错误,ADC还违反了可交换性定律a + b == b + a
。)
也就是说,您指出您的训练板表现出相同的行为。我没有8085培训板,您也没有说您拥有哪一块,所以我无法重现这种现象。我认为您的训练板可能与GNUSim8085具有相同的错误。根据板上是否有8085克隆,这甚至有可能是GNUSim8085的“兼容错误的错误”案例。然而,这只是所有猜测。