X86 Assembly/Arithmetic
All arithmetic instructions are executed in (one of) the ALUs. The ALU can only perform integer arithmetics, for floating point instructions see chapter “Floating Point”.
Basic operationsEdit
Arithmetic instructions take two operands: a destination and a source.
 The destination must be a register or a memory location.
 The source may be either a memory location, a register, or a constant value.
Note that at least one of the two must be a register, because operations may not use a memory location as both a source and a destination.
Addition and SubtractionEdit
add addend, destination  GAS Syntax 
add destination, addend  Intel Syntax 
This adds addend to destination and stores the result in destination.
sub subtrahend, destination  GAS Syntax 
sub destination, subtrahend  Intel Syntax 
Like add
, only it subtracts subtrahend from destination instead.
In C: destination = subtrahend;
MultiplicationEdit
Unsigned MultiplicationEdit
mul multiplicand
This multiplies multiplicand by the value of corresponding bytelength in the accumulator.
width of multiplicand  1 byte  2 bytes  4 bytes  8 bytes 
corresponding multiplier  AL

AX

EAX

RAX

product higher part stored in  AH

DX

EDX

RDX

product lower part stored in  AL

AX

EAX

RAX

In the second case, the target is not EAX
for backward compatibility with code written for older processors.
Affected flags are:
 OF ≔ higher part of product ≠ 0
 CF ≔ higher part of product ≠ 0
All other flags are undefined.
Signed MultiplicationEdit
imul multiplicand
This instruction is almost like mul
, but it treats the sign bit (the MSB), differently.
The imul
instruction also accepts two other formats:
imul src, dest  GAS Syntax 
imul dest, src  Intel Syntax 
imul multiplicand, destination  GAS Syntax 
imul destination, multiplicand  Intel Syntax 
This multiplies destination by multiplicand and puts the result, the product, in destination
imul multiplicand, multiplier, product  GAS Syntax 
imul product, multiplier, multiplicand  Intel Syntax 
This multiplies multiplier by multiplicand and places it into product.
DivisionEdit
div divisor
This divides the value in the dividend register(s) by divisor, see table below.
width of divisor  1 byte  2 bytes  4 bytes  8 bytes 
dividend  AX

DX ￮ AX

EDX ￮ EAX

RDX ￮ RAX

remainder stored in  AH

DX

EDX

RDX

quotient stored in  AL

AX

EAX

RAX

The circle (￮) means concatenation.
With divisor size 4, this means that EDX
are the bits 3263 and EAX
are bits 031 of the input number (with lower bit numbers being less significant, in this example).
As you typically have 32bit input values for division, you often need to use CDQ to signextend EAX
into EDX
just before the division.
If quotient does not fit into quotient register, arithmetic overflow interrupt occurs. All flags are in undefined state after the operation.
idiv arg
As div
, only signed.
Sign InversionEdit
neg arg
Arithmetically negates the argument (i.e. two's complement negation).
Carry Arithmetic InstructionsEdit
adc src, dest  GAS Syntax 
adc dest, src  Intel Syntax 
Add with carry. Adds src
+ CF
to dest
, storing result in dest
. Usually follows a normal add instruction to deal with values twice as large as the size of the register. In the following example, source
contains a 64bit number which will be added to destination
.
mov eax, [source] ; read low 32 bits
mov edx, [source+4] ; read high 32 bits
add [destination], eax ; add low 32 bits
adc [destination+4], edx ; add high 32 bits, plus carry
sbb src, dest  GAS Syntax 
sbb dest, src  Intel Syntax 
Subtract with borrow. Subtracts src
+ CF
from dest
, storing result in dest
. Usually follows a normal sub instruction to deal with values twice as large as the size of the register.
Increment and DecrementEdit
IncrementEdit
inc augend
Increments the register value in the argument by 1.
Performs much faster than add arg, 1
.
DecrementEdit
dec minuend
OperationEdit
Decrements the value in minuend by 1, but this is much faster than the equivalent sub minuend, 1
.
OperandsEdit
Minuend may be either a register or memory operand.
ApplicationEdit
 Some programming language represent Boolean values with either all bits zero, or all bits set to one. When you are programming Boolean functions you need to take account of this. The
dec
instruction can help you with this. Very often you set the final (Boolean) result based on flags. By choosing an instruction that is opposite of the intended and then decrementing the resulting value you will obtain a value satisfying the programming language’s requirements. Here is a trivial example testing for zero.If you intend to set false the “erroneously” setxor rax, rax ; rax ≔ false (ensure result is not wrong due to any residue) test rdi, rdi ; rdi ≟ 0 (ZF ≔ rax = 0) setnz al ; al ≔ ¬ZF dec rax ; rax ≔ rax − 1
1
will be “fixed” bydec
. If you intend to set true, which is represented by −1, you will decrement the value zero.
Pointer arithmeticEdit
The lea
instruction can be used for arithmetic, especially on pointers.
See chapter “data transfer”, § “load effective address”.