234 lines
5 KiB
ArmAsm
234 lines
5 KiB
ArmAsm
.define WRCH, RDCH, Earray, Erange, Eset
|
|
.define Eiovfl, Eidivz, Eiund, Econv
|
|
.define Estack, Eheap, Eillins, Eoddz
|
|
.define Ecase , Ebadmon, OSBYTE, MON
|
|
.define Ebadlin, Ebadgto, BASE, NBYTES
|
|
.define hol0, IGNMASK, ADDR, PROGNAME
|
|
.define LB, LBl, SP, HP, ERRPROC, UNSIGN
|
|
.define Ytmp, EXG, ARTH, RETURN, SIGN
|
|
.define RETSIZE, TRAPVAL, STACK, BRANCH
|
|
.define start, Push, Pop, STACKTh, STACKTl
|
|
.define F_DUM
|
|
.sect .zero
|
|
.sect .text
|
|
.sect .rom
|
|
.sect .data
|
|
.sect .bss
|
|
.sect .text
|
|
|
|
! DEFINITIONS
|
|
|
|
! The next three definitions are special for the
|
|
! BBC microcomputer
|
|
|
|
WRCH = 0FFEEh ! This subroutine writes the character in
|
|
! register A to the screen
|
|
RDCH = 0FFE0h ! This subroutine returns a character in
|
|
! register A from the current input stream
|
|
OSBYTE = 0FFF4h ! This subroutine performs miscelaneous
|
|
! operating system calls
|
|
|
|
F_DUM = 0 ! Dummy floating point constant
|
|
|
|
! Here are the error numbers
|
|
|
|
Earray = 0
|
|
Erange = 1
|
|
Eset = 2
|
|
Eiovfl = 3
|
|
Eidivz = 6
|
|
Eiund = 8
|
|
Econv = 10
|
|
Estack = 16
|
|
Eheap = 17
|
|
Eillins = 18
|
|
Eoddz = 19
|
|
Ecase = 20
|
|
Ebadmon = 25
|
|
Ebadlin = 26
|
|
Ebadgto = 27
|
|
MON = 78D0h
|
|
|
|
BASE = 240 ! This is the offset from the localbase
|
|
! for the second localbase
|
|
|
|
STACKTh = 78h ! This is the top of the stack
|
|
STACKTl = 0D0h
|
|
|
|
! Some zeropage declarations
|
|
|
|
.sect .zero
|
|
|
|
RES: .space 76 ! special for the operating system
|
|
|
|
hol0: .space 16 ! the hol0 block
|
|
|
|
IGNMASK: .space 2 ! can hold the ingnore mask
|
|
|
|
ADDR: .space 4 ! used for indirect addressing
|
|
|
|
LB: .space 2 ! the localbase
|
|
|
|
LBl: .space 2 ! the second localbase (localbase-BASE)
|
|
|
|
SP: .space 3 ! the stackpointer (real_stack)
|
|
|
|
HP: .space 2 ! the heap pointer
|
|
|
|
BRANCH: .space 2 ! used for branch instructions
|
|
|
|
ERRPROC: .space 2 ! can hold the address of the error handler
|
|
|
|
Ytmp: .space 1 ! used for intermediate storage in Y
|
|
|
|
EXG: .space 2 ! used by the exchange subroutine Exg
|
|
|
|
ARTH: .space 16 ! used for arithmetic
|
|
|
|
NBYTES: .space 2 ! containes the number of bytes for a block move
|
|
|
|
|
|
RETURN: .space 4 ! the return area
|
|
|
|
RETSIZE: .space 1 ! the size of the object returned
|
|
|
|
SIGN: .space 1 ! the sign of the calculation
|
|
|
|
UNSIGN : .space 1 ! is it signed or unsigned arithmetic
|
|
|
|
TRAPVAL: .space 1 ! intermediate storage of the error number
|
|
|
|
STACK: .space 1 ! contains the hardware stackpointer on
|
|
! entering m_a_i_n for a neat return
|
|
|
|
RESERVED: .space 112 ! used by the operating system
|
|
|
|
.sect .text
|
|
.base 0E02h ! where to start in the BBC micro
|
|
! GENERAL PURPOSE ROUTINES
|
|
|
|
start:
|
|
tsx
|
|
stx STACK ! save stackpointer for exit and error
|
|
|
|
! The following three operating system calls are only
|
|
! for the BBC microcomputer
|
|
|
|
lda #2
|
|
ldx #0
|
|
ldy #0
|
|
jsr OSBYTE ! return control to the keyboard
|
|
lda #15
|
|
ldx #0
|
|
ldy #0
|
|
jsr OSBYTE ! clear all internal buffers
|
|
lda #3
|
|
ldx #5
|
|
ldy #0
|
|
jsr OSBYTE ! output to screen and RS423
|
|
|
|
lda #STACKTl
|
|
sta LB ! set localbase (lowbyte)
|
|
sta SP+2
|
|
lda #0
|
|
sta SP ! set stackpointer (lowbyte)
|
|
sta ERRPROC ! set start address for error handler (lowbyte)
|
|
sta ERRPROC+1 ! set start address for error handler (highbyte)
|
|
sta hol0 ! set the line number (lowbyte)
|
|
sta hol0+1 ! set the line number (highbyte)
|
|
lda #STACKTh
|
|
sta SP+1 ! set the stacpointer (highbyte)
|
|
sta LB+1 ! set the localbase (highbyte)
|
|
lda #[endbss].l
|
|
sta HP ! set the heap pointer (lowbyte)
|
|
lda #[endbss].h
|
|
sta HP+1 ! set the heap pointer (highbyte)
|
|
lda #[PROGNAME].l
|
|
sta hol0+4 ! set fake programname pointer (lowbyte)
|
|
lda #[PROGNAME].h
|
|
sta hol0+5 ! set fake programname pointer (highbyte)
|
|
lda #[beginbss].l
|
|
sta ADDR ! start address of bss block (lowbyte)
|
|
lda #[beginbss].h
|
|
sta ADDR+1 ! start address of bss block (highbyte)
|
|
ldy #0
|
|
lda #0
|
|
4: ldx #[endbss].h ! clear bss block
|
|
cpx ADDR+1
|
|
bcc 1f ! end of bss block reached
|
|
bne 2f
|
|
ldx #[endbss].l
|
|
cpx ADDR
|
|
bcc 1f ! end of bss block reached
|
|
2: sta (ADDR),y
|
|
inc ADDR
|
|
bne 3f
|
|
inc ADDR+1
|
|
3: jmp 4b
|
|
1: lda #0
|
|
tax
|
|
jsr Push ! push fake envelope pointer
|
|
lda #[PROGNAME].h
|
|
ldx #[PROGNAME].l
|
|
jsr Push ! push argv[0]
|
|
lda #0
|
|
ldx #1
|
|
jsr Push ! push argc
|
|
jsr _m_a_i_n ! start the real program
|
|
|
|
lda #0FFh
|
|
jsr WRCH ! send end of program to R423
|
|
lda #3
|
|
ldx #0
|
|
jsr OSBYTE ! send output to screen only
|
|
lda #2
|
|
ldx #1
|
|
jsr OSBYTE ! input only from R423
|
|
rts
|
|
|
|
|
|
! The subroutine Push pushes the registerpair AX onto the stack.
|
|
|
|
Push:
|
|
sty Ytmp ! save Y
|
|
ldy SP+2
|
|
bne 1f ! lowbyte of stackpointer <> 0
|
|
dec SP+1 ! decrement highbyte of stackpointer
|
|
1: dey
|
|
dey ! decrement lowbyte of stackpointer
|
|
sty SP+2 ! save lowbyte of stackpointer
|
|
pha ! save A
|
|
txa
|
|
sta (SP),y ! push X onto the stack
|
|
iny
|
|
pla ! get A
|
|
sta (SP),y ! push A onto the stack
|
|
ldy Ytmp ! restore Y
|
|
rts
|
|
|
|
|
|
! The subroutine Pop pops the registerpair AX from the stack.
|
|
|
|
Pop:
|
|
sty Ytmp ! save Y
|
|
ldy SP+2
|
|
lda (SP),y ! pop X from the stack
|
|
tax
|
|
iny
|
|
lda (SP),y ! pop A from the stack
|
|
iny
|
|
bne 1f ! lowbyte of stackpointer <> 0
|
|
inc SP+1 ! increment highbyte of stackpointer
|
|
1: sty SP+2 ! store lowbyte of stackpointer
|
|
pha ! save A
|
|
pla ! get A
|
|
ldy Ytmp ! restore Y
|
|
rts
|
|
|
|
|
|
.sect .data
|
|
PROGNAME: ! for initialising the programname pointer
|
|
.asciz "program"
|
|
.sect .bss
|
|
beginbss:
|