Los bits del resultado se obtienen de la suma truncada de enteros sin signo. La instrucción add no se preocupa por el signo aquí ni le importa su propia interpretación de los enteros como firmados o no. Simplemente agrega como si los números no estuvieran firmados.
El indicador de acarreo (o tomar prestado en caso de resta) es el noveno bit inexistente de la suma de los enteros sin signo de 8 bits. Efectivamente, este indicador significa un desbordamiento/subdesbordamiento para agregar/subde números enteros sin signo. Nuevamente, add no se preocupa por los signos aquí, solo agrega como si los números no estuvieran firmados.
Agregar dos números negativos de complemento a 2 dará como resultado el ajuste del indicador de acarreo en 1, correcto.
El indicador de desbordamiento muestra si se ha producido un desbordamiento/desbordamiento para agregar/sumar enteros. Para configurar el indicador de desbordamiento, la instrucción trata los números como firmados (al igual que los trata como no firmados para el indicador de acarreo y los 8 bits del resultado).
La idea de establecer el indicador de desbordamiento es simple. Supongamos que firmas-amplías tus enteros de 8 bits con signo a 9 bits, es decir, solo copias el 7mo bit a un 8vo bit extra. Se producirá un desbordamiento/desbordamiento si la suma/diferencia de 9 bits de estos enteros firmados de 9 bits tiene valores diferentes en los bits 7 y 8, lo que significa que la suma/resta ha perdido el signo del resultado en el 7mo bit y lo usó para el la magnitud del resultado, o, en otras palabras, los 8 bits no pueden acomodar el bit de signo y una magnitud tan grande.
Ahora, el bit 7 del resultado puede diferir del signo imaginario bit 8 si y solo si el acarreo en la punta 7 y el acarreo en la punta 8 (= carga del bit 7) son diferentes. Eso es porque comenzamos con los sumandos que tienen el bit 7 = bit 8 y solo los diferentes arrastres en ellos pueden afectarlos en el resultado de diferentes maneras.
bandera Así desbordamiento = llevar a cabo-pabellón lleven XOR del bit en el bit 6 7.
Tanto mi y sus formas de calcular el indicador de desbordamiento son correctas. De hecho, ambos se describen en el Z80 CPU User's Manual en la sección "Indicadores de estado de Z80".
Así es como se puede emular la mayor parte de la instrucción ADC en C, en la que no tiene acceso directo a las banderas de la CPU y no puede sacar el máximo provecho de la instrucción ADC de la CPU emulando:
#include <stdio.h>
#include <limits.h>
#if CHAR_BIT != 8
#error char expected to have exactly 8 bits.
#endif
typedef unsigned char uint8;
typedef signed char int8;
#define FLAGS_CY_SHIFT 0
#define FLAGS_OV_SHIFT 1
#define FLAGS_CY_MASK (1 << FLAGS_CY_SHIFT)
#define FLAGS_OV_MASK (1 << FLAGS_OV_SHIFT)
void Adc(uint8* acc, uint8 b, uint8* flags)
{
uint8 a = *acc;
uint8 carryIns;
uint8 carryOut;
// Calculate the carry-out depending on the carry-in and addends.
//
// carry-in = 0: carry-out = 1 IFF (a + b > 0xFF) or,
// equivalently, but avoiding overflow in C: (a > 0xFF - b).
//
// carry-in = 1: carry-out = 1 IFF (a + b + 1 > 0xFF) or,
// equivalently, (a + b >= 0xFF) or,
// equivalently, but avoiding overflow in C: (a >= 0xFF - b).
//
// Also calculate the sum bits.
if (*flags & FLAGS_CY_MASK)
{
carryOut = (a >= 0xFF - b);
*acc = a + b + 1;
}
else
{
carryOut = (a > 0xFF - b);
*acc = a + b;
}
#if 0
// Calculate the overflow by sign comparison.
carryIns = ((a^b)^0x80) & 0x80;
if (carryIns) // if addend signs are different
{
// overflow if the sum sign differs from the sign of either of addends
carryIns = ((*acc^a) & 0x80) != 0;
}
#else
// Calculate all carry-ins.
// Remembering that each bit of the sum =
// addend a's bit XOR addend b's bit XOR carry-in,
// we can work out all carry-ins from a, b and their sum.
carryIns = *acc^a^b;
// Calculate the overflow using the carry-out and
// most significant carry-in.
carryIns = (carryIns >> 7)^carryOut;
#endif
// Update flags.
*flags &= ~(FLAGS_CY_MASK | FLAGS_OV_MASK);
*flags |= (carryOut << FLAGS_CY_SHIFT) | (carryIns << FLAGS_OV_SHIFT);
}
void Sbb(uint8* acc, uint8 b, uint8* flags)
{
// a - b - c = a + ~b + 1 - c = a + ~b + !c
*flags ^= FLAGS_CY_MASK;
Adc(acc, ~b, flags);
*flags ^= FLAGS_CY_MASK;
}
const uint8 testData[] =
{
0,
1,
0x7F,
0x80,
0x81,
0xFF
};
int main(void)
{
unsigned aidx, bidx, c;
printf("ADC:\n");
for (c = 0; c <= 1; c++)
for (aidx = 0; aidx < sizeof(testData)/sizeof(testData[0]); aidx++)
for (bidx = 0; bidx < sizeof(testData)/sizeof(testData[0]); bidx++)
{
uint8 a = testData[aidx];
uint8 b = testData[bidx];
uint8 flags = c << FLAGS_CY_SHIFT;
printf("%3d(%4d) + %3d(%4d) + %u = ",
a, (int8)a, b, (int8)b, c);
Adc(&a, b, &flags);
printf("%3d(%4d) CY=%d OV=%d\n",
a, (int8)a, (flags & FLAGS_CY_MASK) != 0, (flags & FLAGS_OV_MASK) != 0);
}
printf("SBB:\n");
for (c = 0; c <= 1; c++)
for (aidx = 0; aidx < sizeof(testData)/sizeof(testData[0]); aidx++)
for (bidx = 0; bidx < sizeof(testData)/sizeof(testData[0]); bidx++)
{
uint8 a = testData[aidx];
uint8 b = testData[bidx];
uint8 flags = c << FLAGS_CY_SHIFT;
printf("%3d(%4d) - %3d(%4d) - %u = ",
a, (int8)a, b, (int8)b, c);
Sbb(&a, b, &flags);
printf("%3d(%4d) CY=%d OV=%d\n",
a, (int8)a, (flags & FLAGS_CY_MASK) != 0, (flags & FLAGS_OV_MASK) != 0);
}
return 0;
}
salida:
ADC:
0( 0) + 0( 0) + 0 = 0( 0) CY=0 OV=0
0( 0) + 1( 1) + 0 = 1( 1) CY=0 OV=0
0( 0) + 127(127) + 0 = 127(127) CY=0 OV=0
0( 0) + 128(-128) + 0 = 128(-128) CY=0 OV=0
0( 0) + 129(-127) + 0 = 129(-127) CY=0 OV=0
0( 0) + 255( -1) + 0 = 255( -1) CY=0 OV=0
1( 1) + 0( 0) + 0 = 1( 1) CY=0 OV=0
1( 1) + 1( 1) + 0 = 2( 2) CY=0 OV=0
1( 1) + 127(127) + 0 = 128(-128) CY=0 OV=1
1( 1) + 128(-128) + 0 = 129(-127) CY=0 OV=0
1( 1) + 129(-127) + 0 = 130(-126) CY=0 OV=0
1( 1) + 255( -1) + 0 = 0( 0) CY=1 OV=0
127(127) + 0( 0) + 0 = 127(127) CY=0 OV=0
127(127) + 1( 1) + 0 = 128(-128) CY=0 OV=1
127(127) + 127(127) + 0 = 254( -2) CY=0 OV=1
127(127) + 128(-128) + 0 = 255( -1) CY=0 OV=0
127(127) + 129(-127) + 0 = 0( 0) CY=1 OV=0
127(127) + 255( -1) + 0 = 126(126) CY=1 OV=0
128(-128) + 0( 0) + 0 = 128(-128) CY=0 OV=0
128(-128) + 1( 1) + 0 = 129(-127) CY=0 OV=0
128(-128) + 127(127) + 0 = 255( -1) CY=0 OV=0
128(-128) + 128(-128) + 0 = 0( 0) CY=1 OV=1
128(-128) + 129(-127) + 0 = 1( 1) CY=1 OV=1
128(-128) + 255( -1) + 0 = 127(127) CY=1 OV=1
129(-127) + 0( 0) + 0 = 129(-127) CY=0 OV=0
129(-127) + 1( 1) + 0 = 130(-126) CY=0 OV=0
129(-127) + 127(127) + 0 = 0( 0) CY=1 OV=0
129(-127) + 128(-128) + 0 = 1( 1) CY=1 OV=1
129(-127) + 129(-127) + 0 = 2( 2) CY=1 OV=1
129(-127) + 255( -1) + 0 = 128(-128) CY=1 OV=0
255( -1) + 0( 0) + 0 = 255( -1) CY=0 OV=0
255( -1) + 1( 1) + 0 = 0( 0) CY=1 OV=0
255( -1) + 127(127) + 0 = 126(126) CY=1 OV=0
255( -1) + 128(-128) + 0 = 127(127) CY=1 OV=1
255( -1) + 129(-127) + 0 = 128(-128) CY=1 OV=0
255( -1) + 255( -1) + 0 = 254( -2) CY=1 OV=0
0( 0) + 0( 0) + 1 = 1( 1) CY=0 OV=0
0( 0) + 1( 1) + 1 = 2( 2) CY=0 OV=0
0( 0) + 127(127) + 1 = 128(-128) CY=0 OV=1
0( 0) + 128(-128) + 1 = 129(-127) CY=0 OV=0
0( 0) + 129(-127) + 1 = 130(-126) CY=0 OV=0
0( 0) + 255( -1) + 1 = 0( 0) CY=1 OV=0
1( 1) + 0( 0) + 1 = 2( 2) CY=0 OV=0
1( 1) + 1( 1) + 1 = 3( 3) CY=0 OV=0
1( 1) + 127(127) + 1 = 129(-127) CY=0 OV=1
1( 1) + 128(-128) + 1 = 130(-126) CY=0 OV=0
1( 1) + 129(-127) + 1 = 131(-125) CY=0 OV=0
1( 1) + 255( -1) + 1 = 1( 1) CY=1 OV=0
127(127) + 0( 0) + 1 = 128(-128) CY=0 OV=1
127(127) + 1( 1) + 1 = 129(-127) CY=0 OV=1
127(127) + 127(127) + 1 = 255( -1) CY=0 OV=1
127(127) + 128(-128) + 1 = 0( 0) CY=1 OV=0
127(127) + 129(-127) + 1 = 1( 1) CY=1 OV=0
127(127) + 255( -1) + 1 = 127(127) CY=1 OV=0
128(-128) + 0( 0) + 1 = 129(-127) CY=0 OV=0
128(-128) + 1( 1) + 1 = 130(-126) CY=0 OV=0
128(-128) + 127(127) + 1 = 0( 0) CY=1 OV=0
128(-128) + 128(-128) + 1 = 1( 1) CY=1 OV=1
128(-128) + 129(-127) + 1 = 2( 2) CY=1 OV=1
128(-128) + 255( -1) + 1 = 128(-128) CY=1 OV=0
129(-127) + 0( 0) + 1 = 130(-126) CY=0 OV=0
129(-127) + 1( 1) + 1 = 131(-125) CY=0 OV=0
129(-127) + 127(127) + 1 = 1( 1) CY=1 OV=0
129(-127) + 128(-128) + 1 = 2( 2) CY=1 OV=1
129(-127) + 129(-127) + 1 = 3( 3) CY=1 OV=1
129(-127) + 255( -1) + 1 = 129(-127) CY=1 OV=0
255( -1) + 0( 0) + 1 = 0( 0) CY=1 OV=0
255( -1) + 1( 1) + 1 = 1( 1) CY=1 OV=0
255( -1) + 127(127) + 1 = 127(127) CY=1 OV=0
255( -1) + 128(-128) + 1 = 128(-128) CY=1 OV=0
255( -1) + 129(-127) + 1 = 129(-127) CY=1 OV=0
255( -1) + 255( -1) + 1 = 255( -1) CY=1 OV=0
SBB:
0( 0) - 0( 0) - 0 = 0( 0) CY=0 OV=0
0( 0) - 1( 1) - 0 = 255( -1) CY=1 OV=0
0( 0) - 127(127) - 0 = 129(-127) CY=1 OV=0
0( 0) - 128(-128) - 0 = 128(-128) CY=1 OV=1
0( 0) - 129(-127) - 0 = 127(127) CY=1 OV=0
0( 0) - 255( -1) - 0 = 1( 1) CY=1 OV=0
1( 1) - 0( 0) - 0 = 1( 1) CY=0 OV=0
1( 1) - 1( 1) - 0 = 0( 0) CY=0 OV=0
1( 1) - 127(127) - 0 = 130(-126) CY=1 OV=0
1( 1) - 128(-128) - 0 = 129(-127) CY=1 OV=1
1( 1) - 129(-127) - 0 = 128(-128) CY=1 OV=1
1( 1) - 255( -1) - 0 = 2( 2) CY=1 OV=0
127(127) - 0( 0) - 0 = 127(127) CY=0 OV=0
127(127) - 1( 1) - 0 = 126(126) CY=0 OV=0
127(127) - 127(127) - 0 = 0( 0) CY=0 OV=0
127(127) - 128(-128) - 0 = 255( -1) CY=1 OV=1
127(127) - 129(-127) - 0 = 254( -2) CY=1 OV=1
127(127) - 255( -1) - 0 = 128(-128) CY=1 OV=1
128(-128) - 0( 0) - 0 = 128(-128) CY=0 OV=0
128(-128) - 1( 1) - 0 = 127(127) CY=0 OV=1
128(-128) - 127(127) - 0 = 1( 1) CY=0 OV=1
128(-128) - 128(-128) - 0 = 0( 0) CY=0 OV=0
128(-128) - 129(-127) - 0 = 255( -1) CY=1 OV=0
128(-128) - 255( -1) - 0 = 129(-127) CY=1 OV=0
129(-127) - 0( 0) - 0 = 129(-127) CY=0 OV=0
129(-127) - 1( 1) - 0 = 128(-128) CY=0 OV=0
129(-127) - 127(127) - 0 = 2( 2) CY=0 OV=1
129(-127) - 128(-128) - 0 = 1( 1) CY=0 OV=0
129(-127) - 129(-127) - 0 = 0( 0) CY=0 OV=0
129(-127) - 255( -1) - 0 = 130(-126) CY=1 OV=0
255( -1) - 0( 0) - 0 = 255( -1) CY=0 OV=0
255( -1) - 1( 1) - 0 = 254( -2) CY=0 OV=0
255( -1) - 127(127) - 0 = 128(-128) CY=0 OV=0
255( -1) - 128(-128) - 0 = 127(127) CY=0 OV=0
255( -1) - 129(-127) - 0 = 126(126) CY=0 OV=0
255( -1) - 255( -1) - 0 = 0( 0) CY=0 OV=0
0( 0) - 0( 0) - 1 = 255( -1) CY=1 OV=0
0( 0) - 1( 1) - 1 = 254( -2) CY=1 OV=0
0( 0) - 127(127) - 1 = 128(-128) CY=1 OV=0
0( 0) - 128(-128) - 1 = 127(127) CY=1 OV=0
0( 0) - 129(-127) - 1 = 126(126) CY=1 OV=0
0( 0) - 255( -1) - 1 = 0( 0) CY=1 OV=0
1( 1) - 0( 0) - 1 = 0( 0) CY=0 OV=0
1( 1) - 1( 1) - 1 = 255( -1) CY=1 OV=0
1( 1) - 127(127) - 1 = 129(-127) CY=1 OV=0
1( 1) - 128(-128) - 1 = 128(-128) CY=1 OV=1
1( 1) - 129(-127) - 1 = 127(127) CY=1 OV=0
1( 1) - 255( -1) - 1 = 1( 1) CY=1 OV=0
127(127) - 0( 0) - 1 = 126(126) CY=0 OV=0
127(127) - 1( 1) - 1 = 125(125) CY=0 OV=0
127(127) - 127(127) - 1 = 255( -1) CY=1 OV=0
127(127) - 128(-128) - 1 = 254( -2) CY=1 OV=1
127(127) - 129(-127) - 1 = 253( -3) CY=1 OV=1
127(127) - 255( -1) - 1 = 127(127) CY=1 OV=0
128(-128) - 0( 0) - 1 = 127(127) CY=0 OV=1
128(-128) - 1( 1) - 1 = 126(126) CY=0 OV=1
128(-128) - 127(127) - 1 = 0( 0) CY=0 OV=1
128(-128) - 128(-128) - 1 = 255( -1) CY=1 OV=0
128(-128) - 129(-127) - 1 = 254( -2) CY=1 OV=0
128(-128) - 255( -1) - 1 = 128(-128) CY=1 OV=0
129(-127) - 0( 0) - 1 = 128(-128) CY=0 OV=0
129(-127) - 1( 1) - 1 = 127(127) CY=0 OV=1
129(-127) - 127(127) - 1 = 1( 1) CY=0 OV=1
129(-127) - 128(-128) - 1 = 0( 0) CY=0 OV=0
129(-127) - 129(-127) - 1 = 255( -1) CY=1 OV=0
129(-127) - 255( -1) - 1 = 129(-127) CY=1 OV=0
255( -1) - 0( 0) - 1 = 254( -2) CY=0 OV=0
255( -1) - 1( 1) - 1 = 253( -3) CY=0 OV=0
255( -1) - 127(127) - 1 = 127(127) CY=0 OV=1
255( -1) - 128(-128) - 1 = 126(126) CY=0 OV=0
255( -1) - 129(-127) - 1 = 125(125) CY=0 OV=0
255( -1) - 255( -1) - 1 = 255( -1) CY=1 OV=0
puede cambiar #if 0
a #if 1
utilizar el método basado en la comparación de inicio de sesión para el cálculo de desbordamiento. El resultado será el mismo. A primera vista, es un poco sorprendente que el método basado en signos también se ocupe del equipaje de mano.
Tenga en cuenta que al usar mi método en el que puedo calcular todos los carry-ins en los bits 0 a 7, también puede obtener de forma gratuita el valor de la bandera half-carry
(acarreo del bit 3 al bit 4) que se necesita para la DAA
instrucción.
EDIT: He agregado una función para la resta con el préstamo (instrucción SBC/SBB) y los resultados.
Esto es perfecto - muchas gracias :-) Yo sabía que estaba en la dirección correcta. Gracias también por su muestra de código. De hecho, estoy usando Java (ya que estoy tratando de que sea un emulador de sistema maestro completamente multiplataforma cuando esté hecho), aunque puedo entender lo suficiente C para ver de qué se trata. Lo siento si mi pregunta parecía simple, es solo que tengo que enseñarme un montón de matemáticas binarias mientras voy con este proyecto, hasta ahora, parece que lo he comprendido :-) – PhilPotter1987
Gracias por su explicación, es realmente preciso . Descubrí la bandera de la mitad de la cola al hacer 'halfCarryOut = carryIn? ((a & 0x0F)> = 0x0F - (a & 0x0F)): ((a & 0x0F)> 0x0F - (a & 0x0F)); halfCarryOut = ((res^a^b) >> 4)^halfCarryOut; ', debería ser correcto. – Jack
@Jack Si lo ha probado y funciona, está bien (no lo voy a validar). Pero se puede hacer de manera más simple, como indiqué al final de la respuesta. Usa la variante de código entre #else y #endif. Después de 'carryIns = * acc^a^b;' do 'halfCarryOut = (carryIns >> 4) & 1;', eso es todo lo que necesita agregar. –