Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could someone please explain what this inline #define assembly is doing?

I'm an occasional C programmer. I've come across this bit of inline assembly code in a Turbo C program

#define ADC(dst,src)    { asm MOV AX, dst;  asm ADD AX, src;  \
              asm ADC AX, 0;    asm MOV dst, AX; }

dst and src are both unsigned 16-bit integers.

It won't compile in GNU C++. Could someone please explain what it's doing? TIA!

like image 321
Jim C Avatar asked Sep 07 '19 14:09

Jim C


2 Answers

The first two instructions add dst and src together, storing the result in the accumulator. The third instruction computes what's sometimes called the "end-around carry" and the fourth stores the result in dst.

The following is an equivalent C implementation:

int32_t sum = dst + (int32_t)src;
dst = (int16_t)((sum & 0xffff) + (sum >> 16));

Wikipedia talks about end-around carry in its coverage of ones' complement:

To add two numbers represented in this system, one does a conventional binary addition, but it is then necessary to do an end-around carry: that is, add any resulting carry back into the resulting sum.

End-around carry is used, for example, when calculating IPv4 checksums.

like image 65
NPE Avatar answered Oct 23 '22 12:10

NPE


A literal translation of this code to GNU C inline assembly is:

static inline short ADC(short dst, short src)
{
     asm ("add %1, %0; adc $0, %0" : "+r"(dst) : "rmi"(src));

     return (dst);
}

But the version provided by NPE should be a bit more portable.

like image 7
fuz Avatar answered Oct 23 '22 12:10

fuz