为了账号安全,请及时绑定邮箱和手机立即绑定

Z80上的溢出和进位标志

/ 猿问

Z80上的溢出和进位标志

三国纷争 2019-12-03 16:23:57

我已经在Z80内核上实现了ADD A,r组操作码。我对我认为已经钉上的进位标志和溢出标志感到有些困惑,但是我想将其发布给社区,以检查我是否正确。

基本上,从我所看到的来看,Z80中的ALU并不关心有符号/无符号操作,它只是添加一些位。这意味着,如果将两个8位值相加并导致9位值相加,则进位标志将被置位。这包括将两个负的二进制补码相加,例如-20(11101100)和-40(11011000),尽管结果为-60(11000100),结果实际上是9位值1 11000100。这肯定意味着如果将两个负的二进制补码值相加,即使没有溢出条件,进位标志也将始终置位-是吗?

其次,我决定要检测该指令中的溢出,我将两个操作数的位7进行XOR,如果结果为10000000,则绝对没有溢出-如果结果为00000000,则可能存在溢出这些符号相同,因此我将加法运算结果的第7位与任一操作数的第7位进行XOR运算,如果运算结果为10000000,则发生了溢出,并设置了P / V溢出标志。我也是在这里吗?

很抱歉遇到这样一个令人费解的问题,我很确定我是对的,但是在基于此逻辑继续进行更多的说明之前,我需要知道。非常感谢。


查看完整描述

3 回答

?
慕少森

从无符号整数的截断和中获得结果的位。add指令在这里既不关心符号,也不关心您自己对有符号或无符号整数的解释。它只是像数字未签名一样添加。


进位标志(或减法时借位)是8位无符号整数相加后的第9位。实际上,此标志表示无符号整数的加/减的上溢/下溢。再说一次,add根本不关心这里的符号,它只是像数字是未签名的那样添加。


将两个负2的补码相加会导致进位标记设置为1,正确。


溢出标志显示有符号整数的加/减是否存在上溢/下溢。要设置溢出标志,该指令将数字视为有符号(就像对于进位标志和结果的8位一样,将它们视为无符号)。


设置溢出标志的思想很简单。假设您将8位带符号整数符号扩展为9位,也就是说,只需将第7位复制到额外的第8位。如果这些9位带符号整数的9位和/差在位7和8中具有不同的值,则将发生上溢/下溢,这意味着加法/减法在第7位中丢失了结果的符号并将其用于结果的大小,换句话说,8位不能容纳符号位,因此幅度太大。


现在,当且仅当进位7的进位和进位8的进位(=从位7进位)不同时,结果的位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;


  // 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 the same

  {

    // 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;

}

输出:


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使用基于符号比较的方法进行溢出计算。结果将是相同的。乍一看,基于符号的方法也可以处理随身携带的情况,这有点令人惊讶。


请注意,通过使用将所有进位值计算half-carry到位0至7的方法,您还将免费获得DAA指令所需的标志值(从位3到位4)。


编辑:我添加了一个借位相减的功能(SBC / SBB指令),并得到了结果。


查看完整回答
反对 回复 2019-12-03
?
慕勒3428872

另一种查看方式可能更容易理解。执行总和时:

  • 符号始终设置为结果的第7位

  • 如果结果为0x00,则设置为零

  • 当操作数的右半字节和溢出时设置半进位

  • 当两个操作数均为正且有符号和为负或两个操作数均为负且有符号和为正时,将设置溢出

  • 添加/订阅被重置

  • 如果无符号和溢出0xFF,则进位被设置


查看完整回答
反对 回复 2019-12-03
?
哆啦的时光机

这确实很准确。我通过这样做找出了半进位标志halfCarryOut = carryIn ? ((a & 0x0F) >= 0x0F - (a & 0x0F)) : ((a & 0x0F) > 0x0F - (a & 0x0F)); halfCarryOut = ((res ^ a ^ b) >> 4) ^ halfCarryOut;,应该是正确的。

查看完整回答
反对 回复 2019-12-03
  • 3 回答
  • 0 关注
  • 78 浏览
我要回答

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信