233 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			233 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:
 |