z80:Advanced Math

From Learn @ Cemetech
Revision as of 21:04, 3 February 2016 by KermMartian (talk | contribs) (Adjusted lowercase z80)
Jump to navigationJump to search

Decimal Math

Addition/Subtraction

To do addition or subtraction on an integer of arbitrary size, we use ADC.


   LD     HL, (word1)        ; Get least-significant word of word1
       LD     DE, (word2)        ; Get least-significant word of word2
       ADD    HL, DE              ; Add them
       LD     (result), HL        ; Store least-significant result
   
       LD     HL, (dword1 + 2)    ; Get most-significant word of word1
       LD     DE, (dword2 + 2)    ; Get most-significant word of word2
       ADC    HL, DE              ; Add them with the carry from the previous addition
       LD     (result + 2), HL    ; Store most-significant result
       RET
   
   word1:    .DB    $B3, $90, $12, $32    ; Each word is stored with the least-significant
   word2:    .DB    $F1, $15, $06, $B8    ; bytes first. You could just as easily have stored
   result:    .DB    $00, $00, $00, $00    ; them in big-endian, but because of how registers are
                                        ; loaded from RAM, it wouldn't work.


Multiplication

For multiplication, we could just add them in a DJNZ loop. But that is slow for multiplying big numbers. So we just do it like in base 10, where we multiply each digit separately.


   .module    DE_Times_A
   DE_Times_A:          ; HL = DE ร— A
       LD     HL, 0      ; Use HL to store the product
       LD     B, 8       ; Eight bits to check
   _loop:
       RRCA             ; Check least-significant bit of accumulator
       JR     NC, _skip  ; If zero, skip addition
       ADD    HL, DE
   _skip:
       SLA    E         ; Shift DE one bit left
       RL     D
       DJNZ   _loop
       RET


Division

Division is also just like base-10 division as well. .module Div_HL_D Div_HL_D: ; HL = HL รท D, A = remainder

   XOR    A         ; Clear upper eight bits of AHL
   LD     B, 16      ; Sixteen bits in dividend

_loop:

   ADD    HL, HL     ; Do a SLA HL
   RLA              ; This moves the upper bits of the dividend into A
   JR     C, _overflow
   CP     D         ; Check if we can subtract the divisor
   JR     C, _skip   ; Carry means D > A

_overflow:

   SUB    D         ; Do subtraction for real this time
   INC    L         ; Set bit 0 of quotient

_skip:

   DJNZ   _loop
   RET

Exponentiation and Logarithms

Conclusion

For more info, see the TI-83 Asm in 28 Days, Day 15 (link below).

For ways to perform more accurate math (Floating Point), there are many prebuilt functions that operate on the OP operators. They can be found here.

Sources: