Reversing : The Hacker's Guide to Reverse Engineering

(ff) #1

Basic Integer Arithmetic


The following section discusses the basic arithmetic operations and how they
are implemented by compilers on IA-32 machines. I will cover optimized addi-
tion, subtraction, multiplication, division, and modulo.
Note that with any sane compiler, any arithmetic operation involving two
constant operands will be eliminated completely and replaced with the result
in the assembly code. The following discussions of arithmetic optimizations
only apply to cases where at least one of the operands is variable and is not
known in advance.

Addition and Subtraction


Integers are generally added and subtracted using the ADDand SUBinstruc-
tions, which can take different types of operands: register names, immediate
hard-coded operands, or memory addresses. The specific combination of
operands depends on the compiler and doesn’t always reflect anything spe-
cific about the source code, but one obvious point is that adding or subtracting
an immediate operand usually reflects a constant that was hard-coded into the
source code (still, in some cases compilers will add or subtract a constant from
a register for other purposes, without being instructed to do so at the source
code level). Note that both instructions store the result in the left-hand
operand.
Subtraction and addition are very simple operations that are performed
very efficiently in modern IA-32 processors and are usually implemented in
straightforward methods by compilers. On older implementations of IA-32 the
LEAinstruction was considered to be faster than ADDand SUB, which brought
many compilers to use LEAfor quick additions and shifts. Here is how the LEA
instruction can be used to perform an arithmetic operation.

lea ecx, DWORD PTR [edx+edx]

Notice that even though most disassemblers add the words DWORD PTR
before the operands, LEAreally can’t distinguish between a pointer and an
integer. LEAnever performs any actual memory accesses.
Starting with Pentium 4 the situation has reversed and most compilers will
use ADDand SUBwhen generating code. However, when surrounded by sev-
eral other ADDor SUBinstructions, the Intel compiler still seems to use LEA.
This is probably because the execution unit employed by LEAis separate from
the ones used by ADDand SUB. Using LEAmakes sense when the main ALUs
are busy—it improves the chances of achieving parallelism in runtime.

522 Appendix B

22_574817 appb.qxd 3/16/05 8:45 PM Page 522

Free download pdf