Uploaded unfinished libraries.
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
#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
|
||||
@@ -0,0 +1,117 @@
|
||||
; Subroutines for printing int16 values to the console.
|
||||
|
||||
#Include print.asm
|
||||
#Include int16.asm
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
SETD PrintInt16dec
|
||||
CALL printInt16dec
|
||||
CALL lineFeed
|
||||
HALT
|
||||
|
||||
printInt16dec:
|
||||
; We're gonna print an int16 as a decimal.
|
||||
; The Data Pointer is set to our int16.
|
||||
; Let's copy it into a temporary location where we can set up an operand.
|
||||
LDA
|
||||
INCD
|
||||
LDB
|
||||
SETD PrintInt16dec
|
||||
STA
|
||||
INCD
|
||||
STB
|
||||
; Load the buffer address into the Data Pointer
|
||||
SETD PrintInt16decBuffer
|
||||
; Let's clear it before we use it.
|
||||
RSTA STA INCD STA INCD STA INCD STA INCD STA
|
||||
PSHD ; Save the offset Data Pointer value to the Stack.
|
||||
printInt16decLoop:
|
||||
SETD PrintInt16dec
|
||||
; Set Operand B to 0d10.
|
||||
DPUP 0x02
|
||||
INIA 0d10
|
||||
RSTB
|
||||
STB
|
||||
INCD
|
||||
STA
|
||||
DPDN 0x03
|
||||
; Now call int16div.
|
||||
CALL int16div
|
||||
; Store the remainder. We only need the low byte.
|
||||
INCD
|
||||
LDA
|
||||
POPD ; Pop the pointer to the current place value from the Stack.
|
||||
STA
|
||||
DECD ; Decrement and store the Data Pointer on the Stack again.
|
||||
PSHD
|
||||
; If the dividend is 0, we're done.
|
||||
INCD
|
||||
LDA
|
||||
INCD
|
||||
LDB
|
||||
OR
|
||||
BRQ printInt16decLoopDone
|
||||
; Now move the quotient up to Operand A.
|
||||
SETD PrintInt16dec
|
||||
DPUP 0x02
|
||||
LDA
|
||||
INCD
|
||||
LDB
|
||||
DPDN 0x03
|
||||
STA
|
||||
INCD
|
||||
STB
|
||||
; Now branch back to the loop.
|
||||
BRI printInt16decLoop
|
||||
printInt16decLoopDone:
|
||||
SETD PrintInt16decBuffer
|
||||
INIB 0x0A
|
||||
printBufferHex:
|
||||
LDA
|
||||
CCF
|
||||
SUB
|
||||
BRQ continue
|
||||
CALL printByteHex
|
||||
CALL blankSpace
|
||||
INCD
|
||||
BRI printBufferHex
|
||||
continue:
|
||||
CALL lineFeed
|
||||
; All we need to do now is pop the Data Pointer value back off the stack and print the digits until we reach a value of 0x0A.
|
||||
POPD
|
||||
SETD PrintInt16decBuffer
|
||||
LDA
|
||||
INIB 0x0A
|
||||
BRA printInt16decSkipLeadingZeros
|
||||
BRI printInt16decLoop1
|
||||
printInt16decSkipLeadingZeros:
|
||||
INCD
|
||||
LDA
|
||||
BRA printInt16decSkipLeadingZeros
|
||||
printInt16decLoop1:
|
||||
LDA
|
||||
CCF
|
||||
SUB
|
||||
; If Q is zero, we've hit the terminator and are done printing.
|
||||
BRQ printInt16decDone
|
||||
CALL printDecimalDigit
|
||||
INCD
|
||||
; Branch back to see if there are more digits to print.
|
||||
BRI printInt16decLoop1
|
||||
printInt16decDone:
|
||||
RET ; Return to the caller.
|
||||
|
||||
|
||||
|
||||
#Data
|
||||
|
||||
PrintInt16dec:
|
||||
0x07 0xD1 ; Operand A
|
||||
0x00 0x00 ; Operand B
|
||||
|
||||
PrintInt16decBuffer:
|
||||
; This needs to be a five byte buffer to store each digit value.
|
||||
; Let's make it six and use the last byte as a terminator outside the range of 0-9.
|
||||
0x00 0x00 0x00 0x00 0x00 0x0A
|
||||
Binary file not shown.
@@ -0,0 +1,88 @@
|
||||
; This file supplies basic support for int8 values.
|
||||
|
||||
#Program
|
||||
|
||||
; Basic int8 subroutines.
|
||||
|
||||
; An int8 value is an 8 bit unsigned integer. Just a byte literally interpreted as a value.
|
||||
; Basic operations on int8 values use A and B as operands with the result returned in Q, similar to the bare arithmetic instructions of SplitBit.
|
||||
|
||||
int8mult:
|
||||
; Multiply A by B and return the result in Q.
|
||||
; This subroutine is limited to outputs in the range of 0-255.
|
||||
; It does not reliably return with the Carry Flag set if the result is too large to fit in the range.
|
||||
; First, check if either is zero, and if so, return zero.
|
||||
BRB return0
|
||||
BRA return0
|
||||
PSHB ; Push the multiplier to the stack.
|
||||
PSHA ; Push the multiplicand to the stack.
|
||||
POPB ; Pop the multiplicand into B.
|
||||
RSTA ; Set A to 0.
|
||||
CCF ; Clear the Carry Flag, just in case.
|
||||
int8multLoop:
|
||||
ADD ; Add the multiplicand to A.
|
||||
POPA ; Pop the multiplier into A.
|
||||
DECA ; Subtract one from the multiplier.
|
||||
BRA int8multDone ; If the multiplier becomes zero, we're done.
|
||||
PSHA ; Push the multiplier back to the stack.
|
||||
PSHQ ; Push the running total to the stack.
|
||||
POPA ; Pop the running total into A.
|
||||
BRI int8multLoop
|
||||
return0:
|
||||
RSTA
|
||||
RSTB
|
||||
ADD
|
||||
int8multDone:
|
||||
RET
|
||||
|
||||
int8div:
|
||||
; Divide A by B and return the quotient in Q.
|
||||
; First, check if either A or B are 0, if so, return 0.
|
||||
BRB return0
|
||||
BRA return0
|
||||
; This dance of pushes, pops, and addition creates a quotient counter on the Stack while preserving A and B.
|
||||
PSHA ; Push A to the Stack.
|
||||
PSHB ; Push B to the Stack.
|
||||
RSTA ; Set A and B to 0.
|
||||
RSTB
|
||||
ADD ; Add them together, setting Q to 0.
|
||||
POPB ; Restore B.
|
||||
POPA ; Restore A.
|
||||
PSHQ ; Push a 0 onto the Stack.
|
||||
; The Carry Flag is clear and we can proceed with the division.
|
||||
int8divLoop:
|
||||
SUB ; Subtract B from A.
|
||||
; If we generate a carry we're done.
|
||||
BRC int8divDone
|
||||
; Otherwise, increment the quotient counter and subtract again.
|
||||
POPA ; Pop the quotient counter from the stack.
|
||||
INCA ; Increment it.
|
||||
PSHA ; Push it back onto the stack.
|
||||
PSHQ ; Push the running total onto the stack.
|
||||
POPA ; Pop the runing total into A.
|
||||
BRI int8divLoop ; Branch back to the loop.
|
||||
int8divDone:
|
||||
CCF ; Clear the Carry Flag.
|
||||
POPA ; Pop the quotient into A.
|
||||
RSTB ; Set B to 0.
|
||||
ADD ; Add them together to move the result to Q.
|
||||
RET ; Return to the caller.
|
||||
|
||||
int8mod:
|
||||
; Divide A by B and return the remainder in Q.
|
||||
; If A or B are 0, return 0.
|
||||
BRB return0
|
||||
BRA return0
|
||||
int8modLoop:
|
||||
SUB ; Subtract B from A.
|
||||
BRC int8modDone
|
||||
PSHQ
|
||||
POPA
|
||||
BRI int8modLoop
|
||||
int8modDone:
|
||||
; Add the divisor to Q to get the remainder.
|
||||
CCF
|
||||
PSHQ
|
||||
POPA
|
||||
ADD
|
||||
RET
|
||||
Reference in New Issue
Block a user