COMPUTER MATH
ADDING DATA
There are two basic integer add instructions: the standard ADD and the ADC
(add with carry). Normally, just the standard add is used for binary integers,
but with some code, the add with carry is necessary. Both the ADD and the ADC
instructions will alter the contents of the carry flag to indicate an addition
overflow out of the high bit position, but the ADC will check the contents of
the carry flag at the instruction start and add an extra 1 to the two operands
being added if carry condition is true.
Example of a 32 bit binary integer addition:
;add lower half of 32 bit data to AX
add ax,datalow
;add upper half of 32 bit data to DX
adc dx,datahigh
;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.
;add to accumulator
inc ax
;subtract 1 from memory location data
dec data
NOTES ABOUT USING
THE 80X87 MATH COPROCESSOR
The 80X87 coprocessor is a very powerful math processing unit. It is an
optional math processor that is available for most PC systems. The 80X87 has
eight internal data registers for processing math functions that are separate
from the standard 80X86 registers. Each of the eight 80X87 data registers is 80
bits wide. The 80X87 has several input and output formats: two byte word
integer, four byte short integer, eight byte long integer, ten byte packed decimal,
four byte short real, eight byte long real, and a ten byte temporary real. All
data inside of the 80X87 is handled in the same 80 bit real number format for
math functions. The 80X87 system uses a stack pointer system to index the
internal data registers. The 80X87 data registers are addressed as relative to
their current position in the stack. The stack works in a circular motion from
indexing data register 0 to data register 7 and back to data register 0. The
data at the top of the stack is referenced as ST(0). If you pop data off the
stack, then ST(1) becomes ST(0). If you push data into the stack, then ST(0)
becomes ST(1). The 80X87 is designed to run in parallel with the 80X86 CPU. An
interesting note about 80X87 math is the division by zero which results in an
answer of infinity except when zero is divided by zero which is indefinite.