8085- Strange behaviour of Carry flag

◇◆丶佛笑我妖孽 提交于 2019-12-23 12:02:08

问题


I am using GNUSim8085 (Also the results are same on trainer)

I was getting familiar wih ADC instruction and the instructions below doesnt seem to work the way i want.

stc  ;to make sure carry is set

mvi a,00h  
mvi b,0ffh          

adc b

hlt

I expected the carry flag to be set because we are adding 11111111+00000000+00000001 , so that would obviously yield a carry but the carry flag is not set. Why is this working this way. Can you please explain this.

Also why is carry generated in the below code and not in the above code:

stc  ;to make sure carry is set

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

adc b

hlt

回答1:


Continuing from my previous comment: It is a bug in the function _eef_inst_func_add_with_carry_i in src/8085-instructions.c of the GNUSim8085 source code. Here is the current source code from the master branch, off of GitHub (rev. 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 lines 326 ff. here.

Let's ignore for now:

  • the redundant assignment sys.flag.c = 0;
  • the comment that points towards an earlier bug related to the SBB instruction

The bug is due to eef_data_t being an alias of guint8, and the code checking whether either the addition of data or data_1, which is data + sys.flag.c, converted back to an eef_data_t, to the accumulator, overflows, and setting the carry flag accordingly.

If data == 0xff, then data_1 == 0 because data + sys.flag.c == 0x100, but the result is converted back to an 8-bit unsigned integer in the assignment, losing the most significant bit. Then, eef_is_carry is used to check whether either 0 + 0xff, or 0 + 0 overflows, neither of which is the case. Therefore, the carry bit is cleared. But the actual addition, of course, is 0 + 0x100, which definitely overflows.

I stand by my previous claim that this is a bug. It is illogical to leave the carry flag unset despite the fact that there should be a carry, mathematically, according to the acknowledged rules of long addition. The 8085 specification describes no such special case. And, even if the exception was valid, don't you agree it should be well-documented?

Most importantly, an ADC that behaves like this simply does not work reliably in common use cases. The reason why ADC instructions at the hardware level even exists is to increase speed (and reduce code size) of multi-word additions relative to the ugly alternative of using comparisons and branching. If ADC does not correctly detect all carry conditions, then the command is insufficient, and even useless, in implementing generic multi-word addition. There is no point in having a broken ADC, compared to none at all, in my opinion. (As I stated previously, due to this bug, the ADC also violates the law of commutativity a + b == b + a.)

That said, you pointed out that your trainer board exhibits the same behavior. I do not have an 8085 trainer board, and you did not say which one you have, so I cannot reproduce this behavior. I think it is possible that your trainer board has the same bug as GNUSim8085. Depending on whether there is an 8085 clone on the board, it is even possible that this is an unfortunate case of "bug for bug compatibility" with GNUSim8085. This is however, all speculation at this point.



来源:https://stackoverflow.com/questions/51015812/8085-strange-behaviour-of-carry-flag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!