# 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 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

; Set rax to 4
mov rax, 4

; 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

; 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

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.

Next section: Conditional branching