8085- Странное поведение флага Carry - PullRequest
0 голосов
/ 25 июня 2018

Я использую 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 голосов
/ 25 июня 2018

Продолжая мой предыдущий комментарий: Это ошибка в функции _eef_inst_func_add_with_carry_i в src/8085-instructions.c исходного кода GNUSim8085.Вот текущий исходный код из ветви master, с 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));

См. строки 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, - ни один из случаев .Следовательно, бит переноса очищается.Но фактическим дополнением, конечно, является 0 + 0x100, которое определенно переполняется.

Я поддерживаю свое предыдущее утверждение, что это ошибка.Нелогично оставлять флаг переноса неустановленным, несмотря на то, что математически должен быть перенос, согласно признанным правилам длительного сложения.Спецификация 8085 не описывает такого особого случая.И, даже если исключение было действительным, разве вы не согласны с тем, что оно должно быть хорошо задокументировано?

Самое главное, что АЦП, который ведет себя так, просто не работает надежно в общих случаях использования.Причина, по которой инструкции АЦП даже существуют на аппаратном уровне, заключается в увеличении скорости (и уменьшении размера кода) дополнений из нескольких слов по сравнению с безобразной альтернативой использования сравнений и ветвлений.Если АЦП не правильно определяет все условия переноса, то команда является недостаточной и даже бесполезной для реализации общего сложения из нескольких слов.Нет никакого смысла иметь сломанный АЦП, по сравнению с ним вообще, на мой взгляд.(Как я уже говорил ранее, из-за этой ошибки, АЦП также нарушает закон коммутативности a + b == b + a.)

Тем не менее, вы указали, что на вашей доске тренера такое же поведение.У меня нет тренировочной доски 8085, а вы не сказали, какая у вас, поэтому я не могу воспроизвести это поведение.Я думаю, что возможно, ваша плата тренера имеет ту же ошибку, что и GNUSim8085.В зависимости от того, есть ли на плате клон 8085, даже возможно, что это неудачный случай «ошибки совместимости ошибок» с GNUSim8085.Это, однако, все спекуляции на данный момент.

...