# Assembler subroutines

The Assembler subroutines are another method of using AccuMath in your applications. The main advantage of using the Assembler subroutines is that they are faster than the BASIC subroutines, mainly due to the overhead of the BASIC CALL statement. The main disadvantages of using the Assembler subroutines are that they require the programmer to call the Assembler subroutines using user-exits, and they only provide the primary arithmetic operations: add, subtract, multiply, divide, compare and precision. If execution speed is a priority however, the Assembler subroutines are an acceptable method.

All of the Assembler subroutines (except XPRC) have two modes, implicit precision and explicit precision. Their operation is exactly as described in the preceding section (BASIC subroutines).

When calling the Assembler subroutines, the following statement should be included near the beginning of the program:

```INCLUDE XP XPA.DEFS
```

Each of the Assembler subroutines is defined in the XPA.DEFS item, and may then be referred to by a symbolic name.

The Assembler subroutines are called by using the BASIC OCONV function. The arguments are concatenated together (using attribute marks to separate them), and passed as data to be converted. The AccuMath function is used as the conversion code.

The following sections describe the Assembler subroutines in more detail.

Two arguments may be added together using the XADD or XADDX subroutine. For XADD (or XADDX when PRECISION is omitted), the precision of the result will be the greater of the precision of either of the arguments. For XADDX when PRECISION not null, the result will be rounded to the specified precision.

```RESULT = OCONV(ARG1:AM:ARG2,XADD)
```

## Subtraction

The difference between two arguments (ARG1 - ARG2) may be computed using the XSUB or XSUBX subroutine. For XSUB (or XSUBX when PRECISION is omitted), the precision of the result will be the greater of the precision of either of the arguments. For XSUBX when PRECISION not null, the result will be rounded to the specified precision.

```RESULT = OCONV(ARG1:AM:ARG2,XSUB)
RESULT = OCONV(ARG1:AM:ARG2:AM:PRECISION,XSUBX)
```

## Multiplication

The product of two arguments may be computed using the XMUL or XMULX subroutine. For XMUL, the precision of the result will be the greater of the precision of either of the arguments; that is, the product will be rounded to the precision of the source argument with the greatest precision. For example, if ARG1=2.494 (precision=3) and ARG2=1.23 (precision=2) then RESULT=3.068 (precision=3) which is 3.06762 rounded to precision 3. For XMULX when PRECISION is omitted, the precision of the result will be sum of the precision of each of the arguments. For example, if ARG1=1.25 (precision=2) and ARG2=0.375 (precision=3), then RESULT=0.46875 (precision=5). For XMULX when PRECISION not null, the product will be rounded to the specified precision.

```RESULT = OCONV(ARG1:AM:ARG2,XMUL)
RESULT = OCONV(ARG1:AM:ARG2:AM:PRECISION,XMULX)
```

## Division

The quotient of two arguments (ARG1 / ARG2) may be computed using the XDIV or XDIVX subroutine. For XDIV, the precision of the result will be the greater of the precision of either of the arguments. The least significant digit of the quotient will be rounded correctly. For XDIVX when PRECISION is not null, the result will be rounded to the specified precision. For XDIVX when PRECISION is omitted, the precision of the result will be the default precision (standard default is 14).

```RESULT = OCONV(ARG1:AM:ARG2,XDIV)
RESULT = OCONV(ARG1:AM:ARG2:AM:PRECISION,XDIVX)
```

## Comparison

Two arguments may be compared, and the results (lower, equal, higher) determined. If the first argument is less than the second argument then -1 is returned. If the first argument is greater than the second argument then 1 is returned. If the first argument is equal to the second argument then 0 is returned. For XCMPX, PRECISION is ignored.

```RESULT = OCONV(ARG1:AM:ARG2,XCMP)
RESULT = OCONV(ARG1:AM:ARG2:AM:PRECISION,XCMPX)
```

## Precision

The precision of a value may be set using the XPRC  subroutine. The first argument contains the value whose precision is being changed, and the second argument contains the desired precision. The precision must be a non-negative integer less than 32000.

If the precision of the first argument is greater than the second argument, then the first argument is rounded to precision specified by the second argument. If the precision of the first argument is less than the second argument, then trailing zeros (and possibly a decimal point) are added to the end of the first argument forcing it to precision specified by the second argument.

```RESULT = OCONV(ARG1:AM:ARG2,XPRC)
```