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.

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.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s