X86 Instructions and ARM Architecture

Arithmetic Instructions

Arithmetic instructions

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.

add src, dest GAS Syntax
add dest, src Intel Syntax

This adds src to dest. If you are using the MASM syntax, then the result is stored in the first argument, if you are using the GAS syntax, it is stored in the second argument.

sub src, dest GAS Syntax
sub dest, src Intel Syntax

Like ADD, only it subtracts source from destination instead. In C: dest -= src;


mul arg

This multiplies arg by the value of corresponding byte-length in the AX register.

operand size 1 byte 2 bytes 4 bytes
other operand AL AX EAX
higher part of result stored in AH DX EDX
lower part of result stored in AL AX EAX
result registers used by mul

In the second case, the target is not EAX for backward compatibility with code written for older processors.


imul arg

As mul, only signed. The imul instruction has the same format as mul, but also accepts two other formats like so:

imul src, dest GAS Syntax
imul dest, src Intel Syntax

This multiplies src by dest. If you are using the NASM syntax, then the result is stored in the first argument, if you are using the GAS syntax, it is stored in the second argument.

imul aux, src, dest GAS Syntax
imul dest, src, aux Intel Syntax

This multiplies src by aux and places it into dest. If you are using the NASM syntax, then the result is stored in the first argument, if you are using the GAS syntax, it is stored in the third argument.


div arg

This divides the value in the dividend register(s) by arg, see table below.

divisor size 1 byte 2 bytes 4 bytes
dividend AX DX:AX EDX:EAX
remainder stored in AH DX EDX
quotient stored in AL AX EAX
result registers for div

The colon (:) means concatenation. With divisor size 4, this means that EDX are the bits 32-63 and EAX are bits 0-31 of the input number (with lower bit numbers being less significant, in this example).

As you typically have 32-bit input values for division, you often need to use CDQ to sign-extend 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.


neg arg

Arithmetically negates the argument (i.e. two's complement negation).


Carry Arithmetic Instructions

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 64-bit number which will be added to destination.

moveax,[source]; read low 32 bits
movedx,[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 Decrement

Increment

inc augend

Increments the register value in the argument by 1. Performs much faster than add arg, 1.


Decrement

dec minuend


Operation

Decrements the value in minuend by 1, but this is much faster than the equivalent sub minuend, 1.


Operands

Minuend may be either a register or memory operand.


Application

  • 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.
    xorrax,rax; rax ≔ false (ensure result is not wrong due to any residue)
    testrdi,rdi; rdi ≟ 0 (ZF ≔ rax = 0)
    setnzal; al ≔ ¬ZF
    decrax; rax ≔ rax − 1
    
    If you intend to set false the “erroneously” set 1 will be “fixed” by dec. If you intend to set true, which is represented by −1, you will decrement the value zero.

Pointer arithmetic

The lea instruction can be used for arithmetic, especially on pointers.