sirve que programacion practicas para microprocesador juego instrucciones ensamblador ejemplos datasheet con math assembly z80

math - que - z80 datasheet



Banderas de desbordamiento y transporte en Z80 (2)

Los bits del resultado se obtienen a partir 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.

La bandera de acarreo (o tomar prestado en caso de resta) es el noveno bit inexistente desde 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 de complemento negativos de 2 dará como resultado el ajuste de la bandera de acarreo a 1, correcta.

El indicador de desbordamiento muestra si ha habido un desbordamiento / desbordamiento para agregar / subular números enteros con signo. 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 detrás 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 bit de signo imaginario 8 si y solo si el acarreo en el bit 7 y el acarreo en el bit 8 (= realización 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.

Por lo tanto, indicador de desbordamiento = bandera de transferencia XOR transporta del bit 6 al bit 7.

Tanto mi como tus formas de calcular el indicador de desbordamiento son correctas. De hecho, ambos se describen en el Manual del usuario de la CPU Z80 en la sección "Indicadores de estado de Z80".

Aquí se explica cómo puede emular la mayoría de las instrucciones ADC en C, donde no tiene acceso directo a los indicadores de la CPU y no puede aprovechar al máximo la instrucción ADC de la CPU emuladora:

#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 para usar el método basado en la comparación de signos 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 calculo todos los acarreos en los bits 0 a 7, también obtiene de forma gratuita el valor del indicador de half-carry (transporte del bit 3 al bit 4) que se necesita para la instrucción DAA .

EDITAR: He agregado una función para restar con préstamos (instrucción SBC / SBB) y resultados para ello.

Me he dado la vuelta para implementar ADD A, r conjunto de códigos de operación en mi núcleo Z80. Tuve un poco de confusión sobre las banderas de acarreo y desbordamiento que creo que he clavado, pero quería ponerlo en la comunidad para verificar que estoy en lo correcto.

Básicamente, por lo que puedo ver, la ALU en el Z80 no se preocupa por las operaciones con firma / sin firma, simplemente agrega bits. Esto significa que si se agregan dos valores de 8 bits y causa un valor de 9 bits como resultado de su adición, se establecerá el indicador de acarreo. Esto incluye agregar dos números de complemento de dos negativos, por ejemplo -20 (11101100) y -40 (11011000), ya que aunque el resultado es -60 (11000100), el resultado es en realidad un valor de 9 bits 1 1100 0100. Esto seguramente significa si se agregan dos valores de complemento de dos negativos, la bandera de acarreo siempre se establecerá, incluso cuando no haya condiciones de desbordamiento, ¿estoy en lo cierto?

En segundo lugar, decidí que para detectar un desbordamiento en esta instrucción, haría el bit 7 de XOR de ambos operandos, y si el resultado fuera 10000000, definitivamente no hay desbordamiento. Si el resultado de esto es 00000000, podría haber un desbordamiento. los signos son los mismos, y por lo tanto, el bit 7 de XOR del resultado de la adición con el bit 7 de cualquiera de los operandos, y si el resultado es 10000000, se produce un desbordamiento y configuro el indicador de desbordamiento de P / V. ¿Estoy aquí también?

Perdón por una pregunta tan enrevesada, estoy bastante seguro de que estoy en lo correcto, pero necesito saberlo antes de seguir con innumerables instrucciones basadas en esta lógica. Muchas gracias.


Otra forma de ver esto que quizás sea más fácil de entender. Al realizar una suma:

  • Signo siempre se establece en el bit 7 del resultado
  • Zero se establece si el resultado es 0x00
  • Half-carry se establece cuando la cantidad de mordiscos correcta de los operandos se desborda
  • El desbordamiento se establece cuando ambos operandos son positivos y la suma de signos es negativa o ambos operandos son negativos y la suma firmada es positiva
  • Agregar / Sub se reinicia
  • Carry se establece si la suma sin signo se desborda 0xFF