Can't we use the ADD instruction to add two 16-bit numbers in 8086?

But my professor said that 8086 did this operation in two steps instead of one ...

She is wrong:

According to the 8086 data sheet (page 2-52), adding two 16-bit numbers takes exactly the same time as adding two 8-bit numbers: 3 clock cycles.

There are CPUs (like the 8085) which perform a 16-bit addition in two steps; but the 8086 does not do so.

She said that the carry generated by lower sum won't be carried over if we used ADD instruction directly.

This would mean that the ADD BX, CX operation results in 1200h when adding 12FFh and 0001h.

This is TOTAL NONSENSE:

Even the Z80 CPU (which has only a 4-bit ALU) will calculate a result of 1300h in this addition; the 8086 (or 8088) with its 16-bit ALU will calculate the correct result anyway!

Maybe she is confused with the 8085:

The 8085 would not set all flags (e.g. the zero flag) after a 16-bit addition; however, even the 8085 would calculate the correct result and set the carry flag correctly.

Is her solution the only accepted way of adding two 16-bit numbers?

Every compiler would use the ADD BX, CX instruction in this case.

Your professor wants to see if you have understood how to use the ADC instruction.

For this reason, using ADD BX, CX is not what she wants to see.

However, if she didn't tell you that you should use 8-bit additions only, your solution is correct!


Your first code block produces identical results in BX to your second code block. (And in CF and SF, and I think OF. Not ZF, PF, or AF, though, for obvious reasons.)

16-bit add is not SIMD addition of two separate byte adds. If you want that, use movd xmm0, ebx / movd xmm1, ecx / paddb xmm0, xmm1. MMX / SSE2 paddb is SIMD addition with separate byte elements. Scalar integer add is a single integer addition operation on the entire operand-size, with CF and OF determined according to the top of the register, whatever that is.

You can trivially prove this by constructing a test case where carry propagates across the 8-bit boundary. Single-step this in a debugger and look at registers after the add.

   mov  ax, 0x80
   add  ax, ax          ; ax = 0x0100  = 0x0080 << 1

Or look at compiler output, like https://godbolt.org/z/xKfK6h4d5 where GCC uses add eax, edx to implement addition of two short variables, or any existing examples of code using add to do pointer math, for example.

Perhaps your professor has had to learn assembly herself to teach a course, and doesn't have much experience with it. The fact that add and other integer-register operations are single operations on the whole number is pretty fundamental, and is like that across all(?) ISAs. (Although 8086 is one of the few with partial registers that alias onto low/high halves). Hopefully she can correct her misunderstanding and let the class know how assembly works.