Расчет флагов: различия между версиями
Panther (обсуждение | вклад) (Новая: {{Emuverse}} for 8-bit add/adc, sub/sbc (it's similar with 16-bit opcodes) A=accumulator d=data to be added/subtracted, excluding carry flag r=result after calculation carry: simply ...) |
Panther (обсуждение | вклад) (основное содержание) |
||
(не показана 1 промежуточная версия этого же участника) | |||
Строка 1: | Строка 1: | ||
{{Emuverse}} | {{Emuverse}} | ||
{{TOCright}} | |||
В данной статье описываютя алгоритмы расчета значений регистра состояния процессора (регистра флагов). | |||
В следующих алгоритмах используются следующие обозначения (предполагается, что вычисления 8-битовые): | |||
* '''A''': Аккумулятор, первый операнд; | |||
* '''d''': второй операнд; | |||
* '''r8''': результат вычислений при использовании 8-разрядной переменной; | |||
* '''r16''': результат вычислений при использовании 16-разрядной переменной; | |||
== Перенос == | |||
Установка флага переноса обозначает, что результат предущей операции не уместился в регистре результата. | |||
* для '''r8''': <TT>CY=1</TT> если <tt>A>r</tt> при сложении, <TT>CY=1</TT> если <tt>A<r</tt> при вычитании; | |||
* для '''r16''': просто | |||
** '''<tt>r16>>8&1</tt>''' (Си) | |||
** '''<tt>(r16 shr 8) and 1</tt>''' (Паскаль); | |||
В формулах подразумеватся, что бит переноса самый младший в регистре флагов. | |||
== Ноль и знак == | |||
Установка флага «Ноль» в единицу означает, что результат равен нулю. Флаг знака равен старшему биту результата. | |||
Оба флага удобно устанавливать одновременно по массиву: | |||
<pre> | |||
Flags := Flags or ZERO_SIGN[r8]; | |||
ZERO_SIGN:array [0..255] of byte =( | |||
F_ZERO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00-0F */ | |||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 10-1F */ | |||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20-2F */ | |||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 30-3F */ | |||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40-4F */ | |||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 50-5F */ | |||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60-6F */ | |||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 70-7F */ | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // 80-8F */ | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // 90-9F */ | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // A0-AF */ | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // B0-BF */ | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // C0-CF */ | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // D0-DF */ | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // E0-EF */ | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, | |||
F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN); // F0-FF */ | |||
</pre> | |||
== Четность == | |||
Установка флага четности означает, что количество разрядов результата, равных 1, четное. Далее приведен пример с использованием массива. | |||
<pre> | |||
Flags := Flags or PARITY[r8]; | |||
PARITY:array [0..255] of Byte = ( | |||
F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 00-0F | |||
0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 10-1F | |||
0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 20-2F | |||
F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 30-3F | |||
0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 40-4F | |||
F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 50-5F | |||
F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 60-6F | |||
0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 70-7F | |||
0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 80-8F | |||
F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 90-9F | |||
F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // A0-AF | |||
0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // B0-BF | |||
F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // C0-CF | |||
0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // D0-DF | |||
0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // E0-EF | |||
F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,4); // F0-FF | |||
</pre> | |||
== Частичный перенос == | |||
Частичный перенос аналогичен обычному переносу, но означает, что результат операции над младшими 4-мя битами не уместился в 4 четыре младших бита результата. Этот флаг используется в операциях с двоично-десятичными числами (ВСD); | |||
* '''<tt>(r^A^d)&0x10;</tt>''' (Си); | |||
* '''<tt>(r xor A xor d) and $10;</tt>''' (Паскаль). | |||
В формулах подразумеватся, что бит частичного переноса пятый в регистре флагов. | |||
== Переполнение == | |||
Установка флага переполнения означает, что результат предыдущей операции не уместился в отведенный регистр, если рассматривать операнды как числа со знаком. То есть флаг аналогичен флагу переноса, но только для значений в дополнительном коде. | |||
* Си: | |||
** '''<tt>((A^r)&(d^r))>>5&4</tt>''' после сложения | |||
** '''<tt>((A^d)&(A^r))>>5&4</tt>''' после вычитания | |||
* Паскаль: | |||
** '''<tt>(((A xor r) and (d xor r)) shr 5) and 4</tt>''' после сложения | |||
** '''<tt>(((A xor d) and (A xor r)) shr 5) and 4</tt>''' после вычитания | |||
В указанных формулах предполагается, что флаг переполнения является третьим битом в регистре состояния (справедливо для Z80). | |||
[[Категория:Приёмы программирования]] |
Текущая версия от 11:05, 20 февраля 2008
Этот документ создан для Emuverse и распространяется на условиях лицензии CC-BY-SA-3.0. |
В данной статье описываютя алгоритмы расчета значений регистра состояния процессора (регистра флагов).
В следующих алгоритмах используются следующие обозначения (предполагается, что вычисления 8-битовые):
- A: Аккумулятор, первый операнд;
- d: второй операнд;
- r8: результат вычислений при использовании 8-разрядной переменной;
- r16: результат вычислений при использовании 16-разрядной переменной;
Перенос
Установка флага переноса обозначает, что результат предущей операции не уместился в регистре результата.
- для r8: CY=1 если A>r при сложении, CY=1 если A<r при вычитании;
- для r16: просто
- r16>>8&1 (Си)
- (r16 shr 8) and 1 (Паскаль);
В формулах подразумеватся, что бит переноса самый младший в регистре флагов.
Ноль и знак
Установка флага «Ноль» в единицу означает, что результат равен нулю. Флаг знака равен старшему биту результата.
Оба флага удобно устанавливать одновременно по массиву:
Flags := Flags or ZERO_SIGN[r8]; ZERO_SIGN:array [0..255] of byte =( F_ZERO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00-0F */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 10-1F */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20-2F */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 30-3F */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40-4F */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 50-5F */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60-6F */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 70-7F */ F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // 80-8F */ F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // 90-9F */ F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // A0-AF */ F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // B0-BF */ F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // C0-CF */ F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // D0-DF */ F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, // E0-EF */ F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN, F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN,F_SIGN); // F0-FF */
Четность
Установка флага четности означает, что количество разрядов результата, равных 1, четное. Далее приведен пример с использованием массива.
Flags := Flags or PARITY[r8]; PARITY:array [0..255] of Byte = ( F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 00-0F 0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 10-1F 0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 20-2F F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 30-3F 0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 40-4F F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 50-5F F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 60-6F 0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 70-7F 0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // 80-8F F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // 90-9F F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // A0-AF 0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // B0-BF F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY, // C0-CF 0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // D0-DF 0,F_PARITY,F_PARITY,0,F_PARITY,0,0,F_PARITY,F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0, // E0-EF F_PARITY,0,0,F_PARITY,0,F_PARITY,F_PARITY,0,0,F_PARITY,F_PARITY,0,F_PARITY,0,0,4); // F0-FF
Частичный перенос
Частичный перенос аналогичен обычному переносу, но означает, что результат операции над младшими 4-мя битами не уместился в 4 четыре младших бита результата. Этот флаг используется в операциях с двоично-десятичными числами (ВСD);
- (r^A^d)&0x10; (Си);
- (r xor A xor d) and $10; (Паскаль).
В формулах подразумеватся, что бит частичного переноса пятый в регистре флагов.
Переполнение
Установка флага переполнения означает, что результат предыдущей операции не уместился в отведенный регистр, если рассматривать операнды как числа со знаком. То есть флаг аналогичен флагу переноса, но только для значений в дополнительном коде.
- Си:
- ((A^r)&(d^r))>>5&4 после сложения
- ((A^d)&(A^r))>>5&4 после вычитания
- Паскаль:
- (((A xor r) and (d xor r)) shr 5) and 4 после сложения
- (((A xor d) and (A xor r)) shr 5) and 4 после вычитания
В указанных формулах предполагается, что флаг переполнения является третьим битом в регистре состояния (справедливо для Z80).