# Basic Math

In this section, we'll go over using assembly language to perform some basic math operations like addition and subtraction.

# A basic program template

Here is the basic program we'll be modifying to try out some different math operations:

```
%define sys_exit 60
section .text
global _start
_start:
; Return a number
mov rdi, 7
; End the program
mov rax, sys_exit
syscall
```

All this does is exit the program, returning 7 as the status code. Type this code into a new file called "math.asm". Use the "run" script from the previous section to assemble, link, and run the new "math.asm" program:

`./run math`

You should see the number 7 written out to the console. At the end of this
program, whatever value is left in the `rdi`

register will be returned as the
status code and displayed on the console. This is how we'll see the results of
the math operations in this section.

*Note: the status code can only be an integer from 0 to 255. If you try to
return negative numbers or numbers larger than 255 you'll get weird results.*

# Addition

Addition is performed using the *add* instruction. It takes 2 operands. It adds
the value of the second operand to the first operand. Take a look at this
example:

` add rbx, 3`

This adds the number 3 to whatever value is stored in `rbx`

. The result of the
operation is stored in `rbx`

. So, if `rbx`

is set to 5 before this instruction
executes, it will be set to 8 after this instruction executes (5 + 3 = 8).

In this instruction, the value 3 is called an *immediate*. This means it's a
literal value encoded directly into the instruction. Unlike a register or
memory address, which refer to storage locations that could have any value,
an immediate is a fixed value that never changes.

You can also add two registers together:

` add rax, rbx`

This adds the values of `rax`

and `rbx`

together and stores the result in
`rax`

.

If `rax`

was 2 and `rbx`

was 4, this instruction would change `rax`

to 6
(2 + 4 = 6). `rbx`

would not be changed.

Now let's work a few *add* instructions into the basic program structure from
above:

```
%define sys_exit 60
section .text
global _start
_start:
; Set rbx to 2
mov rbx, 2
; Add 3 to rbx
add rbx, 3
; Set rax to 4
mov rax, 4
; Add rax to rbx
add rbx, rax
; End the program, returning the value in rbx
mov rdi, rbx
mov rax, sys_exit
syscall
```

Line-by-line:

` mov rbx, 2`

The `rbx`

register is undefined at the start of the program. It's *probably*
0, but it's usually considered best practice to avoid making assumptions about
the state of registers unless we set them ourselves. So, we start by giving
`rbx`

a value of 2.

` add rbx, 3`

Now we add 3 to the value in `rbx`

, which was previously set to 2. After this
instruction executes, the value of `rbx`

should be 5.

` mov rax, 4`

Now we set `rax`

to the value 4. This is to demonstrate adding two registers
together in the next instruction.

` add rbx, rax`

This adds the two registers together: `rax`

, which is currently 4, will be
added to `rbx`

, which is currently 5. After this instruction executes, the
result (9) will be stored in `rbx`

.

```
mov rax, sys_exit
mov rdi, rbx
syscall
```

To return the value in `rbx`

, we have to move it into `rdi`

before performing
the *sys_exit* system call. *sys_exit* returns the value in `rdi`

as the exit
status code. In order to see the value in `rbx`

, we have to copy it to `rdi`

before exiting.

Type the program above into the "math.asm" file and run it:

`./run math`

You should see the value "9" written out to the console.

Try changing the values around a bit and seeing how it responds.

# Subtraction

Subtraction works much like addition. To subtract, we use the *sub*
instruction. Like the *add* instruction, it takes 2 operands. It subtracts
the value of the second operand from the value of the first operand and stores
the result in the first operand.

Here's an example:

```
mov rbx, 10
sub rbx, 7
```

This code snippet starts by setting `rbx`

to a value of 10. Then we subtract 7
from that value, leaving `rbx`

with a value of 3. Try working this into the
program above:

```
%define sys_exit 60
section .text
global _start
_start:
; Set rbx to 5
mov rbx, 5
; Add 3 to rbx
add rbx, 3
; Set rax to 2
mov rax, 2
; Subtract rax from rbx twice
sub rbx, rax
sub rbx, rax
; End the program, returning the value in rbx
mov rdi, rbx
mov rax, sys_exit
syscall
```

Let's go through the changed lines one at a time:

```
; Set rbx to 5
mov rbx, 5
```

We start by setting `rbx`

to 5.

```
; Add 3 to rbx
add rbx, 3
```

Next, we add 3 to `rbx`

. After this instruction executes, `rbx`

should be 8
(5 + 3).

```
; Set rax to 2
mov rax, 2
```

Now we set `rax`

to a value of 2.

```
; Subtract rax from rbx twice
sub rbx, rax
sub rbx, rax
```

Here we subtract the value in `rax`

from the value in `rbx`

two times. `rbx`

starts at 8, so `8 - 2 - 2 = 4`

. After these instructions complete, `rbx`

should be set to 4.

Make these edits and re-run the program. Again, try changing some of the values around and seeing how the output of the program responds.

# Multiplication

Multiplication works similarly. Noticing a pattern here? We can multiply values
with the *imul* instruction. Modify "math.asm" to look like this:

```
%define sys_exit 60
section .text
global _start
_start:
; Set rbx to 3
mov rbx, 3
; Multiply rbx by itself
imul rbx, rbx
; Double the value in rbx
imul rbx, 2
; End the program, returning the value in rbx
mov rdi, rbx
mov rax, sys_exit
syscall
```

See if you can work out what value this program will return. Once you have your guess, take a look at the breakdown:

```
; Set rbx to 3
mov rbx, 3
```

We start by setting `rbx`

to an initial value of 3.

```
; Multiply rbx by itself
imul rbx, rbx
```

Next we multiply `rbx`

by itself. 3 * 3 = 9, so this instruction will set `rbx`

to 9.

```
; Double the value in rbx
imul rbx, 2
```

Finally, we multiply the value in `rbx`

by 2, doubling it. The result is 18.

Again, try experimenting with this instruction. Try combining addition, subtraction, and multiplication in the same program.

# Division

Division works a bit differently. *add*, *sub*, and *imul* are pretty flexible,
in that they can operate on basically any combination of registers and/or
immediates. When it comes to the *idiv* operation, things are a bit more
restricted.

First, let's define some terms. In division, a *dividend* is divided by a
*divisor*, yielding a *result* and a *quotient* (or remainder):

Expression | Dividend | Divisor | Result | Quotient (remainder) |
---|---|---|---|---|

14 / 3 = 4 r 2 | 14 | 3 | 4 | 2 |

100 / 13 = 7 r 9 | 100 | 13 | 7 | 9 |

When using the *idiv* instruction, the dividend is always assumed to be stored
in `rdx:rax`

. This is a new notation. `rdx:rax`

means that the value is spread
across two registers: `rdx`

and `rax`

. The purpose of this is to allow the
division of very large numbers that don't fit into a single register.

For now, we have no need to use both registers, so we can keep things simple
by just using `rax`

. However, it's important to realize what's going on.
Whenever we divide a value in `rax`

, we should make sure that `rdx`

is
clear (set to 0) so that it doesn't interfere with the division operation. If
`rdx`

has data in it, it will be included in the division operation and may
produce unexpected results or errors.

A further limitation of the *idiv* instruction is that it can't divide by an
immediate value. This means that the divisor must first be loaded into a
register.

*idiv* stores the result of the operation in `rax`

and the quotient (remainder)
in `rdx`

.

Here's a new example program which demonstrates 100 / 13:

```
%define sys_exit 60
section .text
global _start
_start:
; Set rax to 100 (this is the dividend)
mov rax, 100
; Clear rdx so it doesn't interfere
mov rdx, 0
; Set divisor to 13
mov rbx, 13
; Perform the division
idiv rbx
; End the program, returning the division result in rax
mov rdi, rax
mov rax, sys_exit
syscall
```

This divides 100 by 13 and returns the result: 7. In more detail:

```
; Set rax to 100 (this is the dividend)
mov rax, 100
```

We're going to divide 100 by 13. 100 goes in `rax`

, since the *idiv*
instruction doesn't let us pick what to use as the dividend.

```
; Clear rdx so it doesn't interfere
mov rdx, 0
```

We don't need the added space of the second register to help store the dividend, so we set it to 0 so that it doesn't interfere with the operation.

*Note: 'xor rdx, rdx' is a faster way to set a register to 0. We'll explain it
more in a later section about binary operations.*

```
; Set divisor to 13
mov rbx, 13
```

The divisor can't be an immediate value, it must be a register. So in order to divide by 13, we first have to load that value into a register.

```
; Perform the division
idiv rbx
```

Here the division operation is performed. The value in `rdx:rax`

is divided
by the value in `rbx`

. The result is placed in `rax`

and the remainder is
placed in `rdx`

.

```
; End the program, returning the division result
mov rdi, rax
mov rax, sys_exit
syscall
```

Here we return the result of the division instruction.

Type this program in and run it. You should get a result of 7. Next, verify the remainder. Modify the end of the program to return the remainder instead of the result:

```
; End the program, returning the division remainder
mov rdi, rdx
mov rax, sys_exit
syscall
```

Run it again, and you should see 9 printed to the console. 100 divided by 13 is 7, with a remainder of 9.

Try combining all of these instructions in various ways until you're comfortable with them.