These instructions perform basic arithmetic operations. Operands may be byte, word, double-word or quad-word registers, memory locations, or immediate values. They all modify CPU flags according to the result of operation thereof, which, in turn, lets us change the execution flow depending on the values of certain flags.
Let us take a look at a few basic arithmetic instructions:
- INC: This is short for increment. This instruction adds 1 to the value of its operand. Obviously, the inc instruction, or its counterpart, the dec instruction, may not be used with immediate values. The inc instruction affects certain CPU flags. For example, consider that we take a register (let it be the EAX register for the sake of simplicity), set it to 0, and execute it, as follows:
inc eax
In this case, EAX would equal to 1 and ZF (zero flag, remember?) would be set to 0, meaning that the operation resulted in a non-zero value. On the other hand, if we load the EAX register with the 0xffffffff value and increment it with the inc instruction, the register will become zero and, since zero is the result of the latest operation, ZF would be set then (will have value of 1).
- ADD: This performs simple addition, adding the source operand to the destination operand and storing the resulting value in the destination operand. This instruction affects several CPU flags as well. In the following example, we will add 0xffffffff to the EBX register, which has been set to 1. The result of such an operation would be a 33-bit value, but as we only have 32 bits to store the result, the extra bit would go into the carry flag. Such a mechanism, in addition to being useful for control of the execution flow, may also be used when adding two big numbers (may be even hundreds of bits wide) as we can then process the numbers by smaller portions (of, for example, 32 bits).
- ADC: Talking about addition of big numbers, the adc instruction is the one that allows us to add the value of the carry flag, as set by a previous operation, to the summation of additional two values. For example, if we want to add 0x802597631 and 0x4fe013872, we would then add 0x02597631 and 0xfe013872 first, resulting in 0x005aaea3 and a set carry flag. Then, we would add 8, 4 and, the value of the carry flag:
;Assuming EAX equals to 8 and EBX equals to 4
adc eax, ebx
This would result in 8 + 4 + 1 (where 1 is the implicit operand--the value of the CF) = 0xd, thus, the overall result would be 0xd005aaea3.
The following example illustrates these instructions in more detail:
mov eax, 0 ; Set EAX to 0
mov ebx, eax ; Set EBX to 0
inc ebx ; Increment EBX
; EBX = 1
add ebx, 0xffffffff ; add 4294967295 to EBX
; EBX = 0 and Carry Flag is set
adc eax, 0 ; Add 0 and Carry Flag to EAX
; EAX = 1