# Math

z80 » Beginner

All the mathmatical operations you'll need to start programming can be broken down into four groups:

You can test these and your own math routines using MathTest.asm. In its current form it only supports the answer in the 8 bit register `a`; but, you can follow the directions in the comments to change it to use `hl` in 2 seconds.

Remember also that we are only working with integers here. Floating point math is taken care of in the Binary Coded Decimal section. You can always write your own routines which will probably be faster than TI's, but why reinvent the wheel?

I wouldn't go into any of these routines if either of your operands is zero. Infinite loops and bogus answers are sure to follow.

Seems simple enough, right? You're using the accumulator (`a`) so you load it with one operand and load the other into another 8 bit register. After you've got that setup, go ahead and add them. Let's add 4 and 5 to get 9. Using `add`, the result will be stored in `a`.
```	ld a,4	;one operand
ld b,5	;second operand
add a,b	;a+b (saved in a)```

Don't forget the 16 bit registers. You can appply the same methods to them; but, instead of revolving around the accumulator (`a`), they revolve around `hl`. The advantage of using 16 bit registers is that you can have way bigger operands.

```	ld hl,4000	;4,000
ld de,15000	;15,000

Things can get a little more complicated when you start using the carry flag. The general idea is, add the two operands and, if the carry flag is set, add one to the answer. Don't add one if the carry flag was reset.

This is helpful, let's say, if you want to account for an overflow in the previous calculation. You have a calculation ( `add`, `sub`, `dec`, `inc`, etc.) which may or may not have resulted in an answer that was too big for it to store. The carry flag will be set if so.

```	ld a,200
ld b,150
; way too big
; to store in
; 8 bit register
;max it can hold
; is 255
;carry set!
ld a,4
ld b,5
;carry is set
; so 9+1=10
;10 is stored in
; a```
The practicality of this feature can be seen in the Simulated 16 bit Addition section, if you want to get more indepth.

## Subtraction

Similar but opposite, `sub` is used for subtraction. The value you want subtracted from is loaded into the accumulator (`a`), the value you want to subtract is put into another register, and then you are ready to perform the actual subtraction.
```	ld a,5	;one operand
ld b,4	;second operand
sub b	;a-b=5-4=1
;1 stored in a```
You can get into a mess if you try subtracting a big number from a little number. You won't get the answer you expect and the carry flag will be set.
```	ld a,4	;one operand
ld b,5	;second operand
sub b	;a-b=4-5=-1=255```
From the Two's Compliment section, you can see that a value of -1 means the same as 255. You can go ahead and add this to another 8 bit register and it will be the same as adding -1.
```	ld c,6
ld a,4	;one operand
ld b,5	;second operand
sub b	;a-b=4-5=-1=255
;5 is stored in a```
As with `adc`, there is `sbc`. It works the same way but adds one to the number being subtracted if the carry is set (not the number subtracted from).
```	ld a,200
ld b,150
; way too big
; to store in
; 8 bit register
;max it can hold
; is 255
;carry set!
ld a,5
ld b,3
sbc a,b		;5-(3+1)=1
;carry is set
; so 3+1=4
; 5-4=1
;1 is stored in a```

## Multiplication

If you haven't figured it out yet, there aren't any instructions to directly multiply. You have to mix some `add`'s, `sub`'s, shifts, and rotates to get what you want. The first few examples assume the answer doesn't excede the capacity of an 8 bit register (255).

You've been through elementary school, you know how the basics of multiplication: add repeatedly.

Since it's always better to use code that you understand, this routine is about as simple as it gets. `B` is one operand and `c` is the other with the answer in `a`

```	sub a	;zero a
or b	;is b=0?
ret z	;exit if b=0 so ret
multiply_loop:
djnz multiply_loop```
The effect is that `c` is repeatedly added to itself, the very idea of multiplication in 6 bytes!

There are two drawbacks to this method.

1. The larger the numbers, the more loops executed, the slower the routine.
2. The answer can't excede 255 or there's an overflow. You need to use 16 bit registers.

Time is of the essence, you need a fast routine. You need to multiply a number (`x`) loaded in `a` to a constant--let's try 2 first. The advantage of using a constant is that you don't need loops, it goes through the code once and only once. You know exactly how long it's going to take.

`	add a,a	;a=a=2*a`
That simple! Try times 5.
```	ld b,a	;save it away temporarily
Eight is a good number too.
```	add a,a	;*2
Try another odd number like 13 using `sub` too. Just subtract the original a few times.
```	ld b,a	;save it away temporarily
sub b	;a*16-a
sub b	;a*15-a
sub b	;a*14-a=13*a```
None of these will hold an answer over 255. Try using 16 bit register pairs to multiply 35 and `hl`.
```	ld d,h		;save it away temporarily
ld e,l		;save it away temporarily

In some cases, it's easier to add in that saved away original at an earlier date, like when the constant is not near a power of 2. 20's like that.

```	ld b,a	;save away original
If we didn't add in the original early like above, our code would be a lot longer!
```	ld b,a	;save away original
It's a good thing we thought ahead. Sometimes you might have to add in the original a couple times along the way.

## Division

Similiar to multiplication, just use subtraction.

Let's divide `a` by `b` (`a`/`b`). In this routine, the answer is stored into `a`. Remember that this is for integers that divide evenly. If you have two numbers that you know do not divide evenly, you will get an infinite loop usually (Your calculator has crashed).

```	ld c,\$00
divide_loop:
inc c
sub b
jr nz,divide_loop
ld a,c
ret```
If you don't mind the final answer stored in `c`, and want to save a byte.
```	ld c,\$00
divide_loop:
inc c
sub b
ret z
jr divide_loop```
This is similiar to the basic multiplication routine: subtract repeatedly. This routine will also exit if `a` is zero and become slower the larger the operands are (more loops).

Let's divide `a` by a constant of 8 using `srl a`.

```	srl a	;/2
srl a	;/4
srl a	;/8```
I don't recommend using shift logically because it's two bytes long. It is nice because it shifts the bits right out of here. Rotate is faster but it just circulates those bits to the other side. If you're going to use rotate, make sure to mask off those bits using `and`. This is one byte shorter. You'll save more bytes if you divide by higher powers of 2 (8=2^3=2*2*2)
```	and %11111000	;mask off (get
; rid of) last
; three bits which
; will be rotated
; out
;we don't want them
; coming back in
; on the other side
rrca		;/2
rrca		;/4
rrca		;/8```

More from z80 » Beginner
Aliases // Convert from decimal to hexadecimal or binary // Flags and Conditions // Format and Compiling // Instructions // Math // Number Bases // Oh, No! It Crashed! // Registers // TI-BASIC to Asm Comparisons // TI86 Specifications // Two's Compliment // z80 Processor