98 lines
3.2 KiB
NASM
98 lines
3.2 KiB
NASM
#Program
|
|
; int16 subroutines.
|
|
|
|
; An int16 value is a 16 bit unsigned integer, represented by two bytes, in the order most-significant, least-significant.
|
|
|
|
; The basic operations take two sequential int16 values as operands from the Data Memory.
|
|
; They assume that the Data Pointer is set to the high byte of operand A.
|
|
; Operands are stored in a four-byte array in the following order:
|
|
; Operand A, high byte
|
|
; Operand A, low byte
|
|
; Operand B, high byte
|
|
; Operand B, low byte
|
|
; All operations overwrite Operand A. This causes the Data Pointer to point to the result immediately after returning.
|
|
|
|
int16add:
|
|
; Add two int16 values.
|
|
; If the addtion results in a carry, the carry flag will be set.
|
|
CCF ; Clear the Carry Flag, just in case.
|
|
DPUP 0d03 ; Move to Operand B's low byte.
|
|
LDB ; Load it to B.
|
|
DPDN 0d02 ; Move to Operand A's low byte.
|
|
LDA ; Load it to A.
|
|
ADD ; Add them together.
|
|
STQ ; Store the result.
|
|
INCD ; Go to Operand B's high byte.
|
|
LDB ; Load it to B.
|
|
DPDN 0d02 ; Go to Operand A's high byte.
|
|
LDA ; Load it to A.
|
|
ADD ; Add them together.
|
|
STQ ; Store the result.
|
|
RET ; Return to the caller.
|
|
|
|
int16sub:
|
|
; Subtract one int16 value from another.
|
|
; If the addtion results in a carry, the carry flag will be set.
|
|
CCF ; Clear the Carry Flag, just in case.
|
|
DPUP 0d03 ; Move to Operand B's low byte.
|
|
LDB ; Load it to B.
|
|
DPDN 0d02 ; Move to Operand A's low byte.
|
|
LDA ; Load it to A.
|
|
SUB ; Subtract B from A.
|
|
STQ ; Store the result.
|
|
INCD ; Go to Operand B's high byte.
|
|
LDB ; Load it to B.
|
|
DPDN 0d02 ; Go to Operand A's high byte.
|
|
LDA ; Load it to A.
|
|
SUB ; Subtract B from A.
|
|
STQ ; Store the result.
|
|
RET ; Return to the caller.
|
|
|
|
int16div:
|
|
; Divide Operand A by Operand B, store the quotient in Operand B, store the remainder in Operand A.
|
|
; First, check and see if Operand B is zero, and abort if so.
|
|
DPUP 0x02 ; Move to Operand B.
|
|
LDA ; Load the high byte.
|
|
INCD
|
|
LDB ; Load the low byte.
|
|
DPDN 0x03 ; Return the Data Pointer to the start.
|
|
OR ; Do a bitwise OR.
|
|
; If Q is zero, then our dividend was zero, and we can't have that.
|
|
BRQ int16divByZero
|
|
; Otherwise, proceed.
|
|
RSTA ; Set A to 0.
|
|
RSTB ; Set B to 0.
|
|
int16divLoop:
|
|
; Now, subtract the Operand B from Operand A.
|
|
CALL int16sub
|
|
; If that subtraction resulted in a carry, we're done.
|
|
BRC int16divEnd
|
|
; Otherwise, we need to increment the quotient counter.
|
|
INCB ; If this overflows B, we need to increment A.
|
|
BRC int16divCarry
|
|
BRI int16divLoop
|
|
int16divCarry:
|
|
INCA
|
|
BRI int16divLoop
|
|
int16divEnd:
|
|
; Add Operand B to Operand A to obtain the remainder.
|
|
CALL int16add
|
|
; Overwrite Operand B with the quotient.
|
|
DPUP 0x02
|
|
STA
|
|
INCD
|
|
STB
|
|
RET ; Return to the caller.
|
|
int16divByZero:
|
|
; You're not supposed to go here! Set Operand A to zero and return.
|
|
STA ; A is necessarily already zero in order to be here, so just store it.
|
|
INCD
|
|
STA
|
|
RET ; Return to the caller.
|
|
|
|
int16mult:
|
|
; Multiplies two int16 values.
|
|
CCF ; Clear the carry flag.
|
|
DPUP 0d03 ; Move to the low byte of Operand B.
|
|
LDB
|