Может кто-нибудь объяснить, что делает эта встроенная сборка #define?

Я случайный программист на Си. Я встречал этот фрагмент встроенного ассемблера в программе Turbo C

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

dst и src - 16-разрядные целые числа без знака.

Он не скомпилируется в GNU C++. Может кто-нибудь объяснить, что он делает? ТИА!

Ответы

Ответ 1

Первые две инструкции складывают dst и src вместе, сохраняя результат в аккумуляторе. Третья инструкция вычисляет то, что иногда называют "сквозным переносом", а четвертая сохраняет результат в dst.

Ниже приведена эквивалентная реализация C:

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

Википедия рассказывает о сквозном переносе в своем обзоре дополнения:

Для добавления двух чисел, представленных в этой системе, одно выполняет обычное двоичное сложение, но затем необходимо выполнить сквозной перенос: то есть добавить любой результирующий перенос обратно в итоговую сумму.

Конечный перенос используется, например, при расчете контрольных сумм IPv4.

Ответ 2

Дословный перевод этого кода на встроенную сборку GNU C:

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

     return (dst);
}

Но версия, предоставляемая NPE, должна быть более переносимой.