home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 52
/
Amiga_Dream_52.iso
/
RiscOS
/
APP
/
DEVS
/
LIB
/
GSTOBJ.ZIP
/
GstObjects
/
fasttimer
/
Example
/
usingAPCS
< prev
Wrap
Text File
|
1994-09-18
|
4KB
|
116 lines
; example of writing assembler for use in APCS environment
; in STM/LDM instructions rx..ry indicates any combinations
; (0 or more) of x..y may be present
; x$stack_overflow and x$stack_overflow_1 are provided by
; the run time kernel
;------------------------------------------------------------------------------------------------------
; this next block identifies this routine
; should a backtrace be required
= "procedure name",0
ALIGN
& &FF0000xx ; xx is positive offset from this word back to start of string
; eg "abcde",0 needs a value of &FF000008 (remember to include padding from ALIGN)
procedure
MOV ip,sp
; optional instruction to save arguments on entry
; STMDB sp!,{r0..r3}
STMDB sp!,{r4..r9,fp,ip,lr,pc}
SUB fp,ip,#4
; only one of the following 3 peices of code should be used next
; depending on amount of stack used etc
; (1) procedure will use no more than 512 bytes of stack and
; will not call an external procedure
; (internal routines can be considered as part of this one
; provided they use a fixed amount of stack)
; no code required
; guaranteed 512 bytes of space left on stack
; (2) procedure will use no more than 256 bytes of stack and
; may call an external procedure
CMP sp,sl
BLLO |x$stack_overflow|
; (3) (a) procedure may use more than 512 bytes of stack
; (and may or may not call external procedure)
; OR
; (b) procedure may use more than 256 bytes of stack and
; may call external procedure
SUB ip,sp,#amount_of_stack_space_needed_in_bytes
CMP ip,sl
BLLO |x$_stack_overflow_1|
; typical instruction to drop sp for local space
SUB sp,sp,#amount_of_stack_space_needed_in_bytes
; more code which uses local space,
; always accessed using postive offsets from sp
; eg STR r0,[sp,#positive_offset]
; main procedure body
; to access arguments which may have been pushed on stack
; also access with -ve offsets from fp
; eg LDR r0,[fp,#negative_offset]
; remember to count stack use of internal subroutines
; as part of this procedure
BL internal_subroutine
; when calling an external procedure,
; sl,sp must be valid
BL external_procedure
; on return: r0-r3,ip,lr may be corrupted; r4-r9,sl,fp are preserved
; PSR flags are preserved
; (lr corrupted implies it may contain anything, not just the return
; address setup by the BL)
; more code
; must preserve sl,fp
; may corrupt r0-r3,ip,lr
; may corrupt r4..r9 but only if they are stacked at entry/exit
; when returning sl,fp must be valid
MOV r0,#return_value
; return with value in r0
LDMDB fp,{r4..r9,fp,sp,pc}^
;------------------------------------------------------------------------------------------------------
EXTRA NOTES:
In leaf procedures (ones that call no other external procedures)
various optimisations can be made to the entry/exit sequence.
eg
procedure
LDR r0,[r0,#Offset]
MOVS pc,lr
It is important that a procedure always returns the flags using lr
(usually stacked) and not the flags on entry. Consider the following
example of a tail-optimised procedure calling an external procedure:
procedureA
CMP r0,#value
MOVLO r1,#constX
MOVHS r1,#constY
B procedureB
If procedureB was to restore the flags it saw on entry
(not those in lr) then it will return to A's caller with the
wrong flags.