Read this article, which gives two examples of instructions set architectures (ISAs). Look over how the different microprocessors address memory. Take note of similarities and differences of format, instructions and type of instructions, and addressing modes between these two as well as between these and the MIPS instructions of the previous sections.
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|
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;
arg by the value of corresponding byte-length in the
|operand size||1 byte||2 bytes||4 bytes|
|higher part of result stored in||
|lower part of result stored in||
In the second case, the target is not
EAX for backward compatibility with code written for older processors.
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|
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|
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
This divides the value in the dividend register(s) by
arg, see table below.
|divisor size||1 byte||2 bytes||4 bytes|
|remainder stored in||
|quotient stored in||
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
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.
div, only signed.
Arithmetically negates the argument (i.e. two's complement negation).
|adc src, dest||GAS Syntax|
|adc dest, src||Intel Syntax|
Add with carry. Adds
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
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
dest, storing result in
dest. Usually follows a normal sub instruction to deal with values twice as large as the size of the
Increments the register value in the argument by 1. Performs much faster than
add arg, 1.
Decrements the value in minuend by 1, but this is much faster than the equivalent
sub minuend, 1.
Minuend may be either a register or memory operand.
decinstruction 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
1will be “fixed” by
dec. If you intend to set true, which is represented by −1, you will decrement the value zero.
lea instruction can be used for arithmetic, especially on pointers.