x86 Assembly Language Reference Manual

# Arithmetic Logical Instructions

```add{bwl} 	reg[8|16|32], r/m[8|16|32]
##### Operation

reg[8|16|32] + r/m[8|16|32] -> r/m[8|16|32]

r/m[8|16|32] + reg[8|16|32] -> reg[8|16|32]

imm[8|16|32] + r/m[8|16|32] -> r/m[8|16|32]

##### Description

Integer adds operand1 to operand2 and stores the result in operand2.

When an immediate byte is added to a word or long, the immediate value is sign-extended to the size of the word or long operand.

If you wish to decimal adjust (daa) or ASCII adjust (aaa) the add result, use the form of add that stores the result in AL.

##### Example

Integer adds the 8-bit constant, -126, to the content of the AL register:

`addb \$-126,%al`

Integer adds the word contained in the effective address (addressed by the EDI register plus an offset of 4) to the content of the DX register:

`addw 4(%edi),%dx`

Integer adds the content of the EDX register to the effective address (addressed by the EDI register plus an offset of 4):

`addl %edx, 4(%edi)`

```adc{bwl} 	reg[8|16|32], r/m[8|16|32]
##### Operation

(reg[8|16|32] + CF) + r/m[8|16|32] -> r/m[8|16|32]

(r/m[8|16|32] + CF) + reg[8|16|32] -> reg[8|16|32]

(imm[8|16|32] + CF) + r/m[8|16|32] -> r/m[8|16|32]

##### Description

Integer adds operand1 and the carry flag to operand2 and stores the result in operand2. adc is typically executed as part of a multi-byte or multi-word add operation. When an immediate byte is added to a word or long, the immediate value is sign-extended to the size of the word or long operand.

##### Example

Integer add the 8-bit content of the effective memory address (ESI register plus an offset of 1) and the carry flag to the content of the address in the CL register:

`adcb 1(%esi), %cl`

Integer add the 16-bit content of the effective memory address (EDI register plus an offset of 4) and the carry flag to the content of the address in the DX register:

`adcw 4(%edi), %dx`

Integer add the 32-bit content of the address in the EDX register and the carry flag to the effective memory address (EDI register plus an offset of 4):

`adcl %edx, 4(%edi)`

## Integer Subtraction (sub)

```sub{bwl} 	reg[8|16|32], r/m[8|16|32]
sub{bwl} 	r/m[8|16|32], reg[8|16|32]
sub{bwl} 	imm[8|16|32], r/m[8|16|32]```
##### Operation

r/m[8|16|32] - reg[8|16|32] -> r/m[8|16|32]

reg[8|16|32] - r/m[8|16|32] -> reg[8|16|32]

r/m[8|16|32] - imm[8|16|32] -> r/m[8|16|32]

##### Description

Subtracts operand1 from operand2 and stores the result in operand2. When an immediate byte value is subtracted from a word, the immediate value is sign-extended to the size of the word operand before the subtract operation is executed.

If you wish to decimal adjust (das) or ASCII adjust (aas) the sub result, use the form of sub that stores the result in AL.

##### Example

Integer subtract the 8-bit constant, -126, from the content of the effective address (addressed by the ESI register plus an offset of 1):

`subb \$-126, 1(%esi)`

Integer subtract the 16-bit constant, 1234, from the content of the effective address (addressed by the EDI register plus an offset of 4):

`subw \$1234, 4(%edi)`

Integer subtract the 32-bit content of the EDX register from the effective address (addressed by the EDI register plus an offset of 4):

`subl %edx, 4(%edi)`

## Integer Subtraction With Borrow (sbb)

```sbb{bwl} 	reg[8|16|32], r/m[8|16|32]
sbb{bwl} 	r/m[8|16|32], reg[8|16|32]
sbb{bwl} 	imm[8|16|32], r/m[8|16|32]```
##### Operation

r/m[8|16|32] - (reg[8|16|32] + CF) -> r/m[8|16|32]

reg[8|16|32] - (r/m[8|16|32] + CF) -> reg[8|16|32]

r/m[8|16|32] - (imm[8|16|32] + CF) -> r/m[8|16|32]

##### Description

Subtracts (operand1 and the carry flag) from operand2 and stores the result in operand2. When an immediate byte value is subtracted from a word, the immediate value is sign-extended to the size of the word operand before the subtract operation is executed.

##### Example

Integer subtract the 8-bit content of the CL register plus the carry flag from the effective address (addressed by the ESI register plus an offset of 1):

`sbbb %cl, 1(%esi)`

Integer subtract the 16-bit constant, -126, plus the carry flag from the AL register:

`sbbw \$-126, %al`

Integer subtract the 32-bit constant, 12345678, plus the carry flag from the effective address (addressed by the EDI register plus an offset of 4):

`sbbl \$12345678, 4(%edi)`

## Compare Two Operands (cmp)

```cmp{bwl}	 	reg[8|16|32], r/m[8|16|32]
cmp{bwl} 		r/m[8|16|32], reg[8|16|32]
cmp{bwl}	 	imm[8|16|32], r/m[8|16|32]```
##### Operation

r/m[8|16|32] - reg[8|16|32]

reg[8|16|32] - r/m[8|16|32]

r/m[8|16|32] - imm[8|16|32]

##### Description

Subtracts operand1 from operand2, but does not store the result; only changes the flags. cmp is typically executed in conjunction with conditional jumps and the setcc instruction. If an operand greater than one byte is compared to an immediate byte, the immediate byte value is first sign-extended.

##### Example

Compare the 8-bit constant, 0xff, with the content of the AL register:

`cmpb \$0xff, %al`

Compare the 16-bit content of the DX register with the effective address (addressed by the EDI register plus an offset of 4):

`cmpw %dx, 4(%edi)`

Compare the 32-bit content of the effective address (addressed by the EDI register plus an offset of 4) to the EDX register:

`cmpl 4(%edi), %edx`

## Increment by 1 (inc)

```inc{bwl} 		r/m[8|16|32]
```
##### Operation

r/m[8|16|32] + 1 -> r/m[8|16|32]

##### Description

Adds 1 to the operand and does not change the carry flag. Use the add instruction with an immediate value of 1 to change the carry flag,.

##### Example

Add 1 to the contents of the byte at the effective address (addressed by the ESI register plus an offset of 1):

`incb 1(%esi)`

Add 1 to the 16-bit contents of the AX register:

`incw %ax`

`incl 4(%edi)`

## Decrease by 1 (dec)

```dec{bwl}		r/m[8|16|32]
```
##### Operation

r/m[8|16|32] - 1 -> r/m[8|16|32]

##### Description

Subtracts 1 from the operand. Does not change the carry flag. To change the carry flag, use the sub instruction with an immediate value of 1.

##### Example

Subtract 1 from the 8-bit contents of the effective address (addressed by the ESI register plus an offset of 1):

`decb 1(%esi)`

Subtract 1 from the 16-bit contents of the BX register:

`decw %bx`

Subtract 1 from the 32-bit contents of the effective address (addressed by the EDI register plus an offset of 4):

`decl 4(%edi)`

## Logical Comparison or Test (test)

```test{bwl}		reg[8|16|32], r/m[8|16|32]
test{bwl}		r/m[8|16|32], reg[8|16|32]
test{bwl}		imm[8|16|32], r/m[8|16|32]```
##### Operation

reg[8|16|32] and r/m[8|16|32] -> r/m[8|16|32]

r/m[8|16|32] and reg[8|16|32] -> reg[8|16|32]

imm[8|16|32] and r/m[8|16|32] -> r/m[8|16|32]

##### Description

Performs a bit-wise logical AND of the two operands. The result of a bit-wise logical AND is 1 if the value of that bit in both operands is 1; otherwise, the result is 0. test discards the results and modifies the flags. The OF and CF flags are cleared; SF, ZF and PF flags are set according to the result.

##### Example

Perform a logical AND of the constant, 0xff, and the 8-bit contents of the effective address (addressed by the ESI register plus an offset of 1):

`testb \$0xff, 1(%esi)`

Perform a logical AND of the 16-bit contents of the DX register and the contents of the effective address (addressed by the EDI register plus an offset of 4):

`testw %dx, 4(%edi)`

Perform a logical AND of the constant, 0xffeeddcc, and the 32-bit contents of the effective address (addressed by the EDI register plus an offset of 4):

`testl \$0xffeeddcc, 4(%edi)`

## Shift (sal, shl, sar, shr)

shl{bwl} %cl, r/m[8|16|32] sar{bwl} imm8, r/m[8|16|32] sar{bwl} %cl, r/m[8|16|32] shr{bwl} imm8, r/m[8|16|32]

```sal{bwl} 	%cl, r/m[8|16|32]
shl{bwl} 	imm8, r/m[8|16|32]
sal{bwl} 	imm8, r/m[8|16|32]
shr{bwl} 	%cl, r/m[8|16|32]```
##### Operation

shift-left r/m[8|16|32] by imm8 -> r/m[8|16|32]

shift-left r/m[8|16|32] by %cl -> r/m[8|16|32]

shift-right r/m[8|16|32] by imm8 -> r/m[8|16|32]

shift-right r/m[8|16|32] by %cl -> r/m[8|16|32]

##### Description

sal (or its synonym shl) left shifts (multiplies) a byte, word, or long value for a count specified by an immediate value and stores the product in that byte, word, or long respectively. The second variation left shifts by a count value specified in the CL register. The high-order bit is shifted into the carry flag; the low-order bit is set to 0.

sar right shifts (signed divides) a byte, word, or long value for a count specified by an immediate value and stores the quotient in that byte, word, or long respectively. The second variation right shifts by a count value specified in the CL register. sar rounds toward negative infinity; the high-order bit remains unchanged.

shr right shifts (unsigned divides) a byte, word, or long value for a count specified by an immediate value and stores the quotient in that byte, word, or long respectively. The second variation divides by a count value specified in the CL register. shr sets the high-order bit to 0.

##### Example

Right shift, count specified by the constant (253), the 8-bit contents of the effective address (addressed by the ESI register plus an offset of 1):

`sarb \$253, 1(%esi)`

Right shift, count specified by the contents of the CL register, the 16-bit contents of the effective address (addressed by the EDI register plus an offset of 4):

`shrw %cl, 4(%edi)`

Left shift, count specified by the constant (253), the 32-bit contents of the effective address (addressed by the EDI register plus an offset of 4):

`shll \$253, 4(%edi)`

## Double Precision Shift Left (shld)

```shld{wl}		imm8, reg[16|32], r/m[16|32]
shld{wl}		%cl, reg[16|32], r/m[16|32]```
##### Operation

by imm8 shift-left r/m[16|32] bits reg[16|32] -> r/m[16|32]

by reg[16|32] shift-left r/m[16|32] bits r/m[16|32] -> r/m[16|32]

##### Description

shld double-precision left shifts a 16- or 32-bit register value into a word or long for the count specified by an immediate value, MODULO 32 (0 to 31). The result is stored in that particular word or long.

The second variation of shld double-precision left shifts a 16- or 32-bit register or memory value into a word or long for the count specified by register CL MODULO 32 (0 to 31).The result is stored in that particular word or long.

shld sets the SF, ZF, and PF flags according to the value of the result; CS is set to the value of the last bit shifted out; OF and AF are undefined.

##### Example

Use the count specified by the constant, 253, to double-precision left shift a 16-bit register value from the DX register to the effective address (addressed by the EDI register plus an offset of 4):

`shldw \$253, %dx, 4(%edi)`

Use the count specified (%CL MOD 32) by the 32-bit EDX register to double-precision left shift a 32-bit memory value at the effective address (addressed by the EDI register plus an offset of 4):

`shldl %cl,%edx, 4(%edi)`

## Double Precision Shift Right (shrd)

```shrd{wl}		imm8, reg[16|32], r/m[16|32]
shrd{wl}		%cl, reg[16|32], r/m[16|32]```
##### Operation

by imm8 shift-right r/m[16|32] bits reg[16|32] -> r/m[16|32]

by reg[16|32] shift-right r/m[16|32] bits r/m[16|32] -> r/m[16|32]

##### Description

shrd double-precision right shifts a 16- or 32-bit register value into a word or long for the count specified by an immediate value MODULO 32 (0 to 31). The result is stored in that particular word or long.

The second variation of shrd double-precision right shifts a 16- or 32-bit register or memory value into a word or long for the count specified by register CL MODULO 32 (0 to 31).The result is stored in that particular word or long.

shrd sets the SF, ZF, and PF flags according to the value of the result; CS is set to the value of the last bit shifted out; OF and AF are undefined.

##### Example

Use the count specified by the constant, 253, to double-precision right shift a 16-bit register value from the DX register to the effective address (addressed by the EDI register plus an offset of 4):

`shrdw \$253, %dx, 4(%edi)`

Use the count specified (%CL MOD 32) by the 32-bit EDX register to double-precision right shift a 32-bit memory value at the effective address (addressed by the EDI register plus an offset of 4)

`shrdl %cl,%edx, 4(%edi)`

## One's Complement Negation (not)

```not{bwl}	 	r/m[8|16|32]
```
##### Operation

not r/m[8|16|32] -> r/m[8|16|32]

##### Description

Inverts each bit value of the byte, word, or long; that is, every 1 becomes a 0 and every 0 becomes a 1.

##### Example

Invert each of the 8-bit values at the effective address (addressed by the ESI register plus an offset of 1):

`notb 1(%esi)`

Invert each of the 16-bit values at the effective address (addressed by the EDI register plus an offset of 4):

`notw 4(%edi)`

Invert each of the 32-bit values at the effective address (addressed by the EDI register plus an offset of 4):

`notl 4(%edi)`

## Two's Complement Negation (neg)

```neg{bwl} 	r/m[8|16|32]
```
##### Operation

two's-complement r/m[8|16|32] -> r/m[8|16|32]

##### Description

Replace the value of the byte, word, or long with its two's complement; that is, neg subtracts the byte, word, or long value from 0, and puts the result in the byte, word, or long respectively.

neg sets the carry flag to 1, unless initial value of the byte, word, or long is 0. In this case neg clears the carry flag to 0.

##### Example

Replace the 8-bit contents of the effective address (addressed by the ESI register plus an offset of 1) with its two's complement:

`negb 1(%esi)`

Replace the 16-bit contents of the effective address (addressed by the EDI register plus an offset of 4) with its two's complement:

`negw 4(%edi)`

Replace the 32-bit contents of the effective address (addressed by the EDI register plus an offset of 4) with its two's complement:

`negl 4(%edi)`

## Check Array Index Against Bounds (bound)

```bound{wl}		reg[16|32], r/m[16|32]
```
##### Operation

r/m[16|32] bound reg[16|32] -> CC is unchanged

##### Description

Ensures that a signed array index (16- or 32-bit register) value falls within the upper and lower bounds of a block of memory. The upper and lower bounds are specified by a 16- or 32-bit register or memory value. If the signed array index value is not within the bounds, an Interrupt 5 occurs; the return EIP points to the bound instruction.

##### Example

Check the 16-bit signed array index value in the AX register against the doubleword with the upper and lower bounds specified by DX:

`boundw %ax, %dx`

Check the 32-bit signed array index value in the EAX register against the doubleword with the upper and lower bounds specified by EDX:

`boundl %eax, %edx`

## Logical And (and)

```and{bwl} 	reg[8|16|32], r/m[8|16|32]
and{bwl} 	r/m[8|16|32], reg[8|16|32]
and{bwl} 	imm[8|16|32], r/m[8|16|32]```
##### Operation

reg[8|16|32] land r/m[8|16|32] -> r/m[8|16|32]

r/m[8|16|32] land reg[8|16|32] -> reg[8|16|32]

imm[8|16|32] land r/m[8|16|32] -> r/m[8|16|32]

##### Description

Performs a logical AND of each bit in the values specified by the two operands and stores the result in the second operand.

Table 2-2 Logical AND

Values

Result

0 LAND 0

0 LAND 1

1 LAND 0

1 LAND 1

##### Example

Perform an 8-bit logical AND of the CL register and the contents of the effective address (addressed by the ESI register plus an offset of 1):

`andb %cl, 1(%esi)`

Perform a 16-bit logical AND of the constant, 0xffee, and the contents of the effective address (addressed by the AX register):

`andw \$0xffee, %ax`

Perform a 32-bit logical AND of the contents of the effective address (addressed by the EDI register plus an offset of 4) and the EDX register:

`andl 4(%edi), %edx`

## Logical Inclusive OR (or)

```or{bwl}  	reg[8|16|32], r/m[8|16|32]
or{bwl}  	r/m[8|16|32], reg[8|16|32]
or{bwl}  	imm[8|16|32], r/m[8|16|32]```
##### Operation

reg[8|16|32] LOR r/m[8|16|32] -> r/m[8|16|32]

r/m[8|16|32] LOR reg[8|16|32] -> reg[8|16|32]

imm[8|16|32] LOR r/m[8|16|32] -> r/m[8|16|32]

##### Description

Performs a logical OR of each bit in the values specified by the two operands and stores the result in the second operand.

Table 2-3 Inclusive OR

Values

Result

0 LOR 0

0 LOR 1

1 LOR 0

1 LOR 1

##### Example

Perform an 8-bit logical OR of the constant, 0xff, and the AL register:

`orb \$0xff, %al`

Perform a 16-bit logical OR of the constant, 0xff83, and the contents of the effective address (addressed by the EDI register plus an offset of 4):

`orw \$0xff83, 4(%edi)`

Perform a 32-bit logical OR of the EDX register and the contents of the effective address (addressed by the EDI register plus an offset of 4):

`orl %edx, 4(%edi)`

## Logical Exclusive OR (xor)

```xor{bwl} 	reg[8|16|32], r/m[8|16|32]
xor{bwl} 	r/m[8|16|32], reg[8|16|32]
xor{bwl} 	imm[8|16|32], r/m[8|16|32]
```
##### Operation

reg[8|16|32] XOR r/m[8|16|32] -> r/m[8|16|32]

r/m[8|16|32] XOR reg[8|16|32] -> reg[8|16|32]

imm[8|16|32] XOR r/m[8|16|32] -> r/m[8|16|32]

##### Description

Performs an exclusive OR of each bit in the values specified by the two operands and stores the result in the second operand.

Table 2-4 Exclusive XOR

Values

Result

0 XOR 0

0 XOR 1

1 XOR 0

1 XOR 1

##### Example

Perform a 8-bit exclusive OR of the constant, 0xff, and the AL register:

`xorb \$0xff, %al`

Perform a 16-bit exclusive OR of the constant, 0xff83, and the contents of the effective address (addressed by the EDI register plus an offset of 4):

`xorw \$0xff83, 4(%edi)`

Perform a 32-bit exclusive OR of the EDX register and the contents of the effective address (addressed by the EDI register plus an offset of 4):

`xorl %edx, 4(%edi)`