Files
SplitBit-Emulator/Programs/testPrograms/serviceReturnTest.asm
T

108 lines
2.7 KiB
NASM

; A software interrupt handing something back.
;
; RETI restores every register from the frame, which is what makes an interrupt safe to
; arrive at an arbitrary moment: the interrupted code cannot tell it happened. A SERVICE is
; not arbitrary - it was asked for - and the same rule means it has no way to answer.
;
; So a service that has something to say writes it INTO ITS OWN FRAME, over the saved
; register, and lets RETI put it back. MVSD is what makes the frame reachable: it copies
; the Stack Pointer into a Data Pointer, and the frame sits just above it.
;
; +1 Status +5 DP3 high +9 DP1 high +13 resume high
; +2 Q +6 DP3 low +10 DP1 low +14 resume low
; +3 A +7 DP2 high +11 DP0 high
; +4 B +8 DP2 low +12 DP0 low
;
; WHICH REGISTERS A SERVICE MAY ANSWER IN is a convention rather than a rule, and it is the
; same one CALL already has: Q and DP3. A subroutine cannot hand back A, B or DP0 to DP2
; because RET puts them back; a service could write over any of them, and should not, for
; exactly the reason the first list exists. A caller expects what it kept to still be there.
;
; ONLY THE HANDLER ITSELF CAN DO THIS. The offsets are from where the Stack Pointer is, and
; a CALL moves it by ten. A routine called by a handler that tried this would be writing
; into its own return address.
;
; Correct output is:
; quiet: 7 a service that says nothing leaves Q as it found it
; answer: 42 one that does, does not
; pointer: ABC and DP3 comes back the same way
#Include console.asm
#Program
start:
; Something recognisable in Q, so that a service leaving it alone is visible.
INIA 0d7
RSTB
CCF
ADD
SETD.0 QuietText
CALL printString
SWI quiet
MVQA
CALL printByteDecimal
CALL newLine
SETD.0 AnswerText
CALL printString
SWI answer
MVQA
CALL printByteDecimal
CALL newLine
SETD.0 PointerText
CALL printString
SWI pointer
PSHD.3
POPD.0
CALL printString
CALL newLine
HALT
; Says nothing, so whatever the caller had in Q is still there afterwards.
quiet:
INIA 0d99
RSTB
CCF
ADD ; Q is 99 in here, and nobody outside will ever know.
RETI
answer:
INIA 0d42
MVSD.1
DPUP.1 0d02 ; The saved Q.
STA.1
RETI
pointer:
SETD.0 Letters
MVSD.1
DPUP.1 0d05 ; The saved DP3, high byte first the way everything is stored.
PSHD.0
POPA ; The low half comes off the Stack first.
POPB
STB.1
INCD.1
STA.1
RETI
#Data
QuietText:
"quiet: "
AnswerText:
"answer: "
PointerText:
"pointer: "
Letters:
"ABC"
#Vectors
Boot start
quiet quiet
answer answer
pointer pointer