Расчет флагов
Этот документ создан для 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).