Files
SplitBit-Emulator/Programs/replCalculator.asm
T
2026-08-13 23:42:55 -04:00

411 lines
4.5 KiB
NASM

; Interactive hexadecimal calculator for SplitBit.
;
; Enter expressions as:
; HH operator HH
; Whitespace is optional. Supported operators are + - * & | and ^.
; Arithmetic wraps to eight bits. Enter Q to quit.
#Include Libraries/print.asm
#Program
start:
SETD Welcome
CALL printString
repl:
SETD Prompt
CALL printString
CALL readNonSpace
PSHQ
POPA
; Q, q, or end-of-file exits.
INIB 0xFF
XOR
BRQ quit
INIB 0x51
XOR
BRQ quit
INIB 0x71
XOR
BRQ quit
CALL readHexByteFirst
SETD LeftOperand
STQ
CALL parseIsInvalid
BRQ inputError
CALL readNonSpace
PSHQ
POPA
SETD Operator
STA
CALL readNonSpace
PSHQ
POPA
CALL readHexByteFirst
SETD RightOperand
STQ
CALL parseIsInvalid
BRQ inputError
CALL discardLine
CALL evaluate
SETD Result
STQ
CALL operatorIsInvalid
BRQ operatorError
SETD Result
LDA
CALL printByteHex
CALL lineFeed
BRI repl
inputError:
CALL discardLine
SETD BadInput
CALL printString
BRI repl
operatorError:
SETD BadOperator
CALL printString
BRI repl
quit:
SETD Goodbye
CALL printString
HALT
; Read a character other than space, tab, CR, or LF. Return it in Q.
readNonSpace:
readNonSpaceLoop:
INA 0x00
INIB 0x20
XOR
BRQ readNonSpaceLoop
INIB 0x09
XOR
BRQ readNonSpaceLoop
INIB 0x0A
XOR
BRQ readNonSpaceLoop
INIB 0x0D
XOR
BRQ readNonSpaceLoop
INIB 0x00
CCF
ADD
RET
; A contains the first hexadecimal digit. Read the second and return the byte
; in Q. Q is 0xFF on malformed input.
readHexByteFirst:
CALL clearParseStatus
CALL hexNibble
PSHQ
POPA
INIB 0xFF
XOR
BRQ invalidByte
INIB 0x00
SHL
SHL
SHL
SHL
PSHA
CALL readNonSpace
PSHQ
POPA
CALL hexNibble
PSHQ
POPA
INIB 0xFF
XOR
BRQ invalidLowNibble
POPB
OR
RET
invalidLowNibble:
POPB
invalidByte:
PSHD
SETD ParseStatus
INIA 0x01
STA
POPD
INIA 0xFF
INIB 0x00
CCF
ADD
RET
; Convert the ASCII hexadecimal digit in A to a value in Q.
; Uppercase and lowercase letters are accepted. Q=0xFF means invalid.
hexNibble:
PSHA
; Try 0 through 9.
INIB 0x30
CCF
SUB
BRC tryUpperHex
PSHQ
POPA
INIB 0d10
CCF
SUB
BRC decimalNibble
tryUpperHex:
POPA
PSHA
INIB 0x41
CCF
SUB
BRC tryLowerHex
PSHQ
POPA
INIB 0d06
CCF
SUB
BRC upperNibble
tryLowerHex:
POPA
PSHA
INIB 0x61
CCF
SUB
BRC badNibble
PSHQ
POPA
INIB 0d06
CCF
SUB
BRC lowerNibble
badNibble:
POPA
INIA 0xFF
INIB 0x00
CCF
ADD
RET
decimalNibble:
POPB
INIB 0x00
CCF
ADD
RET
upperNibble:
POPB
INIB 0d10
CCF
ADD
RET
lowerNibble:
POPB
INIB 0d10
CCF
ADD
RET
; Return Q=0 if Q was 0xFF, otherwise return a nonzero value.
resultIsInvalid:
PSHQ
POPA
INIB 0xFF
XOR
RET
clearParseStatus:
PSHD
SETD ParseStatus
RSTA
STA
POPD
RET
parseIsInvalid:
PSHD
SETD ParseStatus
LDA
INIB 0x01
XOR
POPD
RET
operatorIsInvalid:
PSHD
SETD OperatorStatus
LDA
INIB 0x01
XOR
POPD
RET
; Evaluate the stored expression and return its result in Q.
evaluate:
PSHD
SETD OperatorStatus
RSTA
STA
POPD
SETD Operator
LDA
INIB 0x2B
XOR
BRQ evaluateAdd
INIB 0x2D
XOR
BRQ evaluateSubtract
INIB 0x2A
XOR
BRQ evaluateMultiply
INIB 0x26
XOR
BRQ evaluateAnd
INIB 0x7C
XOR
BRQ evaluateOr
INIB 0x5E
XOR
BRQ evaluateXor
SETD OperatorStatus
INIA 0x01
STA
RSTA
INIB 0x00
CCF
ADD
RET
evaluateAdd:
SETD LeftOperand
LDA
INCD
LDB
CCF
ADD
RET
evaluateSubtract:
SETD LeftOperand
LDA
INCD
LDB
CCF
SUB
RET
evaluateAnd:
SETD LeftOperand
LDA
INCD
LDB
AND
RET
evaluateOr:
SETD LeftOperand
LDA
INCD
LDB
OR
RET
evaluateXor:
SETD LeftOperand
LDA
INCD
LDB
XOR
RET
evaluateMultiply:
RSTA
SETD Product
STA
multiplyLoop:
SETD RightOperand
LDA
BRA multiplyDone
DECA
STA
SETD Product
LDA
SETD LeftOperand
LDB
CCF
ADD
SETD Product
STQ
BRI multiplyLoop
multiplyDone:
SETD Product
LDA
INIB 0x00
CCF
ADD
RET
; Consume the rest of the current input line.
discardLine:
discardLoop:
INA 0x00
INIB 0x0A
XOR
BRQ discardDone
INIB 0xFF
XOR
BRQ discardDone
BRI discardLoop
discardDone:
RET
#Data
LeftOperand:
0x00
RightOperand:
0x00
Operator:
0x00
Product:
0x00
Result:
0x00
ParseStatus:
0x00
OperatorStatus:
0x00
Welcome:
"SplitBit calculator (+ - * & | ^), Q quits."
Prompt:
0x0A
"> "
BadInput:
"Invalid hexadecimal input."
BadOperator:
"Unknown operator."
Goodbye:
"Goodbye!"
0x0A