Accessing flags without inline assembly?

I have the following method in C that takes two 16-bit short ints and:

  • Adds two integers
  • If the carry flag is set, add 1 to the result
  • Negate (NOT) all bits in final results
  • Return the result:

    short __declspec(naked) getchecksum(short s1, short s2)
    {
        __asm
        {
            mov ax, word ptr [esp+4]
            mov bx, word ptr [esp+8]
            add ax, bx
            jnc skip_add
            add ax, 1
            skip_add:
            not ax      
            ret
        }
    }
    
          

I had to write this in inline assembly because I don't know how to test the carry flag without using assembler. Does anyone know a way to do this?

+3


source to share


2 answers


No (C has no concept of flags at all), but that doesn't mean you can't get the same result. If you are using 32 bit integers to add, the 17th bit is carry. Therefore, you can write it like this:

uint16_t getchecksum(uint16_t s1, uint16_t s2)
{
    uint32_t u1 = s1, u2 = s2;
    uint32_t sum = u1 + u2;
    sum += sum >> 16;
    return ~sum;
}

      



I made the types unsigned to prevent problems. This may be optional on your platform.

+5


source


You don't need to refer to flags to do higher precision arithmetic. There is carry if the sum is less than either of the operands, so you can do it like this:

short __declspec(naked) getchecksum(short s1, short s2)
{
    short s = s1 + s2;
    if ((unsigned short)s < (unsigned short)s1)
        s++;
    return ~s;
}

      

There are already many questions about adding and carrying SO: Adding 128-bits efficiently using the carry flag , Adding a verbose word in C



However, in C, operations are always done, at least in int type, so you can just add this if int has more than 16 bits on your system. In your case, inline assembly is 16-bit x86, so I guess you are on Turbo C, which should be removed by ASAP (reason: Why not use Turbo C ++? ). On other systems with 16-bit int, you can use long, which is guaranteed to be at least 32-bit standard

short __declspec(naked) getchecksum(short s1, short s2)
{
    long s = s1 + s2;
    return ~((s & 0xffff) + ((s >> 16) & 0x1));
}

      

+3


source







All Articles