4.2.3 Adding and Subtracting Integers

You can use the ADD, ADC, INC, SUB, SBB, and DEC instructions for adding, incrementing, subtracting, and decrementing values in single registers. You can also combine them to handle larger values that require two registers for storage.

4.2.3.1 Adding and Subtracting Integers Directly

The ADD, INC (Increment), SUB, and DEC (Decrement) instructions operate on 8- and 16-bit values on the 8086–80286 processors, and on 8-, 16-, and 32-bit values on the 80386/486 processors. They can be combined with the ADC and SBB instructions to work on 32-bit values on the 8086 and 64-bit values on the 80386/486 processors (see Section 4.2.3.2).

These instructions have two requirements:

1.If there are two operands, only one operand can be a memory operand.

2.If there are two operands, both must be the same size.

Summary: PTR allows you to operate on data in sizes different from its declared type.

To meet the second requirement, you can use the PTR operator to force an operand to the size required (see Section 4.2, “Integer Operations”). For example, if Buffer is an array of bytes and BX points to an element of the array, you can add a word from Buffer with

add ax, WORD PTR Buffer[bx] ; Adds a word from the

; byte variable

The next example shows 8-bit signed and unsigned addition and subtraction.

DATA

mem8 BYTE 39

.CODE

; Addition

; signed unsigned

mov al, 26 ; Start with register 26 26

inc al ; Increment 1 1

add al, 76 ; Add immediate 76 + 76

; ---- ----

; 103 103

add al, mem8 ; Add memory 39 + 39

; ---- ----

mov ah, al ; Copy to AH -114 142

+overflow

add al, ah ; Add register 142

; ----

; 28+carry

; Subtraction

; signed unsigned

mov al, 95 ; Load register 95 95

dec al ; Decrement -1 -1

sub al, 23 ; Subtract immediate -23 -23

; ---- ----

; 71 71

sub al, mem8 ; Subtract memory -122 -122

; ---- ----

; -51 205+sign

mov ah, 119 ; Load register 119

sub al, ah ; and subtract -51

; ----

; 86+overflow

The INC and DEC instructions treat integers as unsigned values and do not update the carry flag for signed carries and borrows.

Summary: Your programs must include error-recovery for overflows and carries.

When the sum of eight-bit signed operands exceeds 127, the processor sets the overflow flag. (The overflow flag is also set if both operands are negative and the sum is less than or equal to -128.) Placing a JO (Jump on Overflow) or INTO (Interrupt on Overflow) instruction in your program at this point can transfer control to error-recovery statements. When the sum exceeds 255, the processor sets the carry flag. A JC (Jump on Carry) instruction at this point can transfer control to error-recovery statements.

In the subtraction example above, the processor sets the sign flag if the result goes below 0. At this point, you can use a JS (Jump on Sign) instruction to transfer control to error-recovery statements.

4.2.3.2 Adding and Subtracting in Multiple Registers

You can add and subtract numbers larger than the register size on your processor with the ADC (Add with Carry) and SBB (Subtract with Borrow) instructions. If the operations prior to an ADC or SBB instruction do not set the carry flag, these instructions are identical to ADD and SUB. When you operate on large values in more than one register, use ADD and SUB for the least significant part of the number and ADC or SBB for the most significant part.

The following example illustrates multiple-register addition and subtraction. You can also use this technique with 64-bit operands on the 80386/486 processors.

.DATA

mem32 DWORD 316423

mem32a DWORD 316423

mem32b DWORD 156739

.CODE

.

.

.

; Addition

mov ax, 43981 ; Load immediate 43981

sub dx, dx ; into DX:AX

add ax, WORD PTR mem32[0] ; Add to both + 316423

adc dx, WORD PTR mem32[2] ; memory words ------

; Result in DX:AX 360404

; Subtraction

mov ax, WORD PTR mem32a[0] ; Load mem32 316423

mov dx, WORD PTR mem32a[2] ; into DX:AX

sub ax, WORD PTR mem32b[0] ; Subtract low - 156739

sbb dx, WORD PTR mem32b[2] ; then high ------

; Result in DX:AX 159684

For 32-bit registers on the 80386/486, only two steps are necessary. If your program needs to be assembled for more than one processor, you can assemble the statements conditionally, as shown in this example:

.DATA

mem32 DWORD 316423

mem32a DWORD 316423

mem32b DWORD 156739

p386 TEXTEQU (@Cpu AND 08h)

.CODE

.

.

.

; Addition

IF p386

mov eax, 43981 ; Load immediate

add eax, mem32 ; Result in EAX

ELSE

.

. ; do steps in previous example

.

ENDIF

; Subtraction

IF p386

mov eax, mem32a ; Load memory

sub eax, mem32b ; Result in EAX

ELSE

.

. ; do steps in previous example

.

ENDIF

Since the status of the carry flag affects the results of calculations with ADC and SUB, be sure to turn off the carry flag with the CLC (Clear Carry Flag) instruction or use ADD for the first calculation when appropriate.