 Assembly Language: Easy Math

This section explains some of the basics of doing math in Assembly language. There are several hardware and software tricks that can be used to perform math calculations as quickly as possible. This section discusses bit level multiplication with shifts and adds.

Example of a 32 bit binary integer addition:

;add lower half of 32 bit data to AX
;add upper half of 32 bit data to DX
;branch if carry overflow
jc   carryover

SUBTRACTING DATA

There are two basic subtract instructions: the standard SUB and the SBB (subtract with borrow). Normally, for small numbers, the SUB is used for standard binary integer subtraction, but in routines that want to handle subtractions of larger numbers, the subtract with borrow is used. The borrow condition is maintained in the carry flag.

Example of a 32 bit subtraction:

;subtract lower half of 32 bit data from AX
sub  ax,datalow
;subtract upper half of 32 bit data from DX with borrow
sbb  dx,datahigh

MULTIPLYING DATA

There are two basic multiply instructions: the integer unsigned multiply (MUL) and the integer signed multiply (IMUL). The multiply can be either 8 bit or 16 bit format. For the 8 bit multiply, AL has to hold one data variable. The other data variable can come from a register or memory. The 16 bit result will be placed into AX. For the 16 bit multiply, AX has to hold one data variable. The other can come from a register or memory. The 32 bit result will be placed into DX:AX with DX holding the most significant data and AX holding the least significant data.

Examples:

;multiply BX * AX = DX:AX
MUL  BX
;multiply data to accumulator
IMUL data_var

Note that if data_var is a byte, the compiler will generate code for an eight bit by eight bit multiply instruction; if data is a word, then it will generate a 16 bit by 16 bit multiply instruction.

DIVIDING DATA

There are two basic divide instructions: the standard integer unsigned divide (DIV) and the integer signed divide (IDIV). You can divide a 16 bit number by an 8 bit number or you can divide a 32 bit number by a 16 bit number. For the small divide, the AX register has to hold the 16 bit number. The 8 bit number that is used for the small divide can come from either a register or memory. The result will be in AL with the modulo from the divide in AH. For the larger divide, DX:AX holds the 32 bit data with AX holding the least significant bits. The 16 bit data used for the divide can come from a register or memory. The main result data will be put into AX and DX will hold the modulo data resulting from the divide.

Example:

;divide DX:AX by BX = AX modulo DX
DIV  bx
;divide using signed integer AX by databyte = AL modulo AH
IDIV databyte

MULTIPLYING BY LEFT BIT SHIFTING

Shifting a number to the left by one bit position has the effect of multiplying the number by two. Shifting a number to the left by two bit positions has the effect of multiplying the number by four. Shifting a number to the left by three bit positions has the effect of multiplying the number by eight. Each shift doubles the current value of a binary integer variable. In base ten math, shifting a number to the left and putting a zero in the rightmost digit position multiplies the number by ten.

A more elaborate multiplication can be seen with this example. Shift a number left one bit to multiply by two and save the number. Now shift the number left two more times to multiply by eight, then add the saved value of the two multiply and you have the effect of multiplying by ten. Now take this result and shift to the left one more time to double the data value and you have multiplied the starting number by 20.

Example:

mov  ax,01     ;load 1 into ax
shl  ax,1     ;ax now 10B or 2
mov  dx,ax     ;save value
shl  ax,1     ;ax now 100B or 4
shl  ax,1     ;ax now 1000B or 8
add  ax,dx     ;ax now 1010B or 10
shl  ax,1     ;ax now 10100B or 20

INCREMENTING AND DECREMENTING

The INC instruction is a quick way to add one to memory or a register. This is used in many routines that count. The DEC instruction is a quick way to subtract one from memory or a register.