This article defines arithmetic instructions as executed by x86 processors. It goes on to describe in brief, four key classifications of arithmetic instructions: addition, subtraction, multiplication and division.
This article is designed for students and professionals who want to gain detailed understanding of arithmetic instructions, their classifications and how they’re used. Through the use of an 8086-emulator, this article will give you a better understanding of arithmetic instructions, its syntax and in some cases memory flow during execution.
Arithmetic instructions in x86
The arithmetic instructions define the set of operations performed by the processor Arithmetic Logic Unit (ALU). This article will discuss only the four key operations of arithmetic instructions.
Integers in x86
Integers used during arithmetic operations in x86 may be represented in two modes: unsigned and signed. Unsigned integers are always positive or zero. Signed integers can be either positive or negative.
The add instruction sums up the contents of the source operand (second operand) and the destination operand (first operand) and then places the results in the source operand.
destination := destination + source
- ADD AX, 0120H ; Add the hex value 120 to value in the accumulator and keep the sum in the accumulator
- ADD AX, CX ; Add the values in registers CX and AX. Keep the sum in the accumulator
- ADD AX, [DI] ; Add the value at address given by the destination index DI to the register AX. Keep the value in the accumulator
- ADD AX, [5777H] ; Add the value at address 5777 to the accumulator. Keep the sum in the accumulator
- ADD [5777H], 0100H ; Add the hex value 100 to the value at address given by 5777. Keep the sum in the address 5777
Figure 1: Contents of registers prior to the execution of Example 1
As shown in figure 1, the content of the accumulator (register AX) was 0000h before the execution of line 1 in example 1.
Figure 2: Contents of accumulator after line 1 in example 1 is executed
The ADC instruction sums up the destination operand (first operand), the source operand (second operand) and the carry (CF) flag. It then stores the resulting value in the destination operand.
ADC destination, source
destination := destination + source + CF
- ADC AX, 23h ; Add the hex value 23 to the value in register AX and the carry flag. Store sum in register AX
- ADC AX, BX ; Add values in registers AX and BX to the value in the carry flag. Store sum in AX
- ADD AX, CX ; Add values in registers, AX and CX to the value in the carry flag. Store sum in AX
Figure 3: Status of the carry flag and registers AX, BX and CX before execution of instructions in example 2
Figure 4: Status of the carry flag and registers AX, BX and CX after execution of instructions in example 2
Figure 5: Carry flag manually set to 1 before code execution
Figure 6: New value in accumulator
The subtract instruction subtracts the source operand (second operand) from the destination operand (first operand) and the result is stored in the destination operand.
destination := destination – source
- SUB AX, CX ; Subtract value in register CX from value in accumulator. Save results in accumulator
- SUB AX, 01h ; Subtract the hex value 01 from the value in the accumulator. Save results in the accumulator
In Example 3, assume the registers AX and BX are manually initialized as follows:
AX = 1023h
CX = 1726h
Note that these registers can also be initialized by using the instructions:
MOV AX, 1023h;
MOV CX, 1726h;
Figure 7: Registers AX and CX manually initialized before the execution of instructions in example 3
Figure 8: Contents of AX, CX registers and status flags after the instructions in example 3 are executed
Note the contents of status flags as shown in figure 8. This status of the flags has occurred because the value in register CX is greater than the value in register AX.
The mul instruction multiplies an 8-bit, 16-bit or 32-bit operand by either AL, AX or EAX. It multiplies by AL if the operand is 8-bit, by AX if the operand is 16-bit and by EAX if the operand is 32-bit. The operand in this instruction is unsigned.
Figure 9: Signed multiplication in x86
- MOV AX, 20d ; Copy the decimal value 20 to the accumulator
- MOV BX, 10d ; Copy the decimal value 10 to BX
- MUL BX; Multiply the values in AX and BX. Result is saved in AX
Figure 10: Low-order 8 bits multiplication
Figure 11: Status of registers AX and BX after executing instructions in example 4
IMUL uses the same basic format as the MUL instruction to perform signed integer multiplication.
- MOV AL, 30 ; Copy the decimal value 30 to the accumulator
- MOV BL, 3 ; Copy the decimal value 3 to register BL
- IMUL BL ; Multiply the values in registers AL and BL
Because AH is a sign extension of AL, the overflow flag is 0. The overflow flag is set to 1 when AH is not a sign extension of AL.
Figure 12: Contents of status registers, accumulator and register BX before instructions in example 5 are executed
Figure 13: Contents of status registers, accumulator and register BX after instructions in example 5 are executed
The DIV instruction performs 8-bit, 16-bit, and 32-bit division operations on unsigned integers. The single operand is called the divisor and quotient is the result of a division.
Assume we’re dividing 7/3.
- The quotient is 2
- The remainder after integer division is 1
- 7 is called the dividend
- 3 is the divisor
- MOV DX, 0 ; Clear high-order of DX register by setting it to zero
- MOV AX, 30 ; Set the low order of the dividend
- MOV CX, 10 ; Set value for divisor
- DIV CX ; Quotient AX=0003h, DX=0h
This article has explained four key instructions in arithmetic operations. To uniquely aid in the understanding of how these operations work, the article has also presented flow of instructions during their executions.
- Arithmetic Instruction, ScienceDirect
- Unsigned and Signed Integers, nhn.ou.edu