227 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
	
		
			4.9 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
 | |
| 
 | |
| ! 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
 | |
| 
 | |
| .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
 | |
| 
 | |
| .base 0E02h		! where to start in the BBC micro
 | |
| .text
 | |
| ! 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
 | |
| 
 | |
| 
 | |
| .data
 | |
| PROGNAME:		! for initialising the programname pointer
 | |
| .asciz "program"
 | |
| .bss
 | |
| beginbss:
 |