结果的位数来自于无符号整数的截断和。在这里,add指令不关心符号,也不关心您将整数解释为有符号或无符号。它只是像数字无符号一样进行相加。
进位标志(或在减法的情况下借位)是从8位无符号整数相加中得到的不存在的第9位。有效地,该标志表示了无符号整数的加/减溢出/下溢。同样,add在这里完全不关心符号,它只是像数字无符号一样进行相加。
两个负的二进制补码数相加会将进位标志设置为1,正确。
溢出标志显示了是否已经发生了有符号整数的加法/减法溢出/下溢。为了设置溢出标志,指令将数字视为有符号的(就像对于进位标志和结果的8位一样将它们视为无符号的)。
设置溢出标志背后的思想很简单。假设您将8位有符号整数扩展为9位,即只需将第7位复制到额外的第8位即可。如果这些9位有符号整数的9位和/差异在第7位和第8位具有不同的值,则会发生溢出/下溢,这意味着加法/减法在第7位中丢失了结果的符号,并将其用于结果的大小,或者换句话说,8位无法容纳符号位和如此大的大小。
现在,结果的第7位只有在进入第7位和进入第8位(=第7位的进位)不同时才能与虚拟符号位第8位不同。这是因为我们从加数开始,它们的第7位=第8位,并且只有不同的进位可以以不同的方式影响它们在结果中的位置。
所以溢出标志=进位输出标志XOR从第6位进入第7位的进位。
我的计算方法和你的计算方法都是正确的。实际上,在Z80 CPU用户手册的“Z80状态指示器标志”一节中,两种方法都有描述。
以下是如何在C语言中模拟大多数ADC指令的方法,其中您无法直接访问CPU的标志并且无法充分利用模拟CPU的ADC指令:
#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;
if (*flags & FLAGS_CY_MASK)
{
carryOut = (a >= 0xFF - b);
*acc = a + b + 1;
}
else
{
carryOut = (a > 0xFF - b);
*acc = a + b;
}
#if 0
carryIns = ((a ^ b) ^ 0x80) & 0x80;
if (carryIns)
{
carryIns = ((*acc ^ a) & 0x80) != 0;
}
#else
carryIns = *acc ^ a ^ b;
carryIns = (carryIns >> 7) ^ carryOut;
#endif
*flags &= ~(FLAGS_CY_MASK | FLAGS_OV_MASK);
*flags |= (carryOut << FLAGS_CY_SHIFT) | (carryIns << FLAGS_OV_SHIFT);
}
void Sbb(uint8* acc, uint8 b, uint8* flags)
{
*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;
}
输出:
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
你可以将
#if 0
更改为
#if 1
,以使用基于符号比较的方法进行溢出计算。结果将是相同的。乍一看,基于符号的方法也能处理进位。
请注意,通过使用我的方法,在位0到7中计算所有进位值,您还可以免费获得所需的
DAA
指令的
half-carry
标志(从位3到位4的进位)的值。
编辑:我添加了一个带借位的减法函数(SBC/SBB指令)和其结果。
halfCarryOut = carryIn ? ((a & 0x0F) >= 0x0F - (a & 0x0F)) : ((a & 0x0F) > 0x0F - (a & 0x0F)); halfCarryOut = ((res ^ a ^ b) >> 4) ^ halfCarryOut;
找到了半进位标志,应该是正确的。 - JackcarryIns = *acc ^ a ^ b;
之后添加halfCarryOut = (carryIns >> 4) & 1;
,这就是你需要添加的全部内容。 - Alexey Frunze