Расчет флагов: различия между версиями

Материал из Emuverse
(перенос)
(основное содержание)
 
Строка 1: Строка 1:
{{Emuverse}}
{{Emuverse}}
{{TOCright}}
В данной статье описываютя алгоритмы расчета значений регистра состояния процессора (регистра флагов).
В данной статье описываютя алгоритмы расчета значений регистра состояния процессора (регистра флагов).


Строка 9: Строка 11:


== Перенос ==
== Перенос ==
Установка флага переноса обозначает, что результат предущей операции не уместился в регистре результата.
* для '''r8''': <TT>CY=1</TT> если <tt>A&gt;r</tt> при сложении, <TT>CY=1</TT> если <tt>A&lt;r</tt> при вычитании;
* для '''r8''': <TT>CY=1</TT> если <tt>A&gt;r</tt> при сложении, <TT>CY=1</TT> если <tt>A&lt;r</tt> при вычитании;
* для '''r16''': просто  
* для '''r16''': просто
** '''<tt>r16>>8&1</tt>''' (Си)  
** '''<tt>r16>>8&1</tt>''' (Си)
** '''<tt>(r16 shr 8) and 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>''' (Паскаль).


half carry: like you said it's (r^A^d)&0x10
В формулах подразумеватся, что бит частичного переноса пятый в регистре флагов.


overflow: ((A^r)&(d^r))>>5&4 for add, ((A^d)&(A^r))>>5&4 for sub
== Переполнение ==
Установка флага переполнения означает, что результат предыдущей операции не уместился в отведенный регистр, если рассматривать операнды как числа со знаком. То есть флаг аналогичен флагу переноса, но только для значений в дополнительном коде.
* Си:
** '''<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).