Tips and Tricks |
MOV R1, #0 .loop ...do something... ADD R1, R1, #1 CMP R1, #255 BNE loopThat is brain-dead code to do something 255 times. You could replace that code with:
MOV R1, #255 .loop ...do something... SUBS R1, R1, #1 BNE loopWhat, no comparison - but a conditional?
SUB
operation has the S
suffix, so it affects
the flags. An EQ
condition is when the Z bit is set, and a NE
condition
is when the Z bit is unset. And the Z bit being set means....zero!.
STMFD R13!, {v1-v6, sl, fp, ip, sp, lr}unless you actually need to store those registers. If you can work your code in the first four registers with no branching, you don't need to store anything.
Say you use R0, R1 and R2, and you do a few BL
s. Should you be pushing the link
register to the stack?
LDMFD R13!, {R14} ...doing stuff... STMFD R13!, {PC}The code, above, is terribly wasteful. Not only do you use a multiple load/store instruction to preserve one register, but you waste stack space.
MOV R3, R14 ...doing stuff... MOV PC, R3The
S
suffix causes the PSR to be restored.
An optimisation, when it is required to store R14 (and only R14) to the stack is to do something like:
STR R14, [R13, #-4]! ...do stuff... LDR PC, [R13], #4
If you also need to restore the state of the PSR on a 26bit system, you would instead do:
STR R14, [R13, #-4]! ...do stuff... LDR R14, [R13], #4 MOVS PC, R14
1. Synthesise it
MOV R0, #&FF000000 ADD R0, R0, #&00FF0000 ADD R0, R0, #&000000FF
2. Load it
ADR R1, big_word LDR R0, [R1] ... .big_word EQUD &FFFF00FFI prefer to use the Load method, as it tends to make the code clearer, especially when generating large numbers involves trickery with
BIC
, EOR
, and TEQ
.
Loading may save program space - it depends upon how you generate your large number - but causes
the processor to jump around to load the word.
Execution speed depends upon the processor. For example, it has been reported that a load is
faster on a StrongARM, where an ARM 6 gets more speed out of generating the large value from
three instructions.
IF x% = 4 OR x% = 1 THEN ...can be implemented as something like:
[we assume x% has been loaded into R0] CMP R0, #4 CMPNE R0, #1 BEQ ...the code to call when x% = 4 OR 1 ...the ELSE code
CASE something% OF WHEN 0 : PROCzero WHEN 1 : PROCone WHEN 2 : PROCtwo OTHERWISE : PROCinvalid ENDCASEin assembler by code such as (assuming something% is in R0):
CMP R0, #2 ; The immediate value is the range LDRLS PC, [PC, R0, LSL#8] ; Program Counter set to the first EQUD B invalid ; We come here if R0 > 2 EQUD zero EQUD one EQUD two
Or an alternative method:
.entry CMP R0, #((endoftable - table) / 4) ADDCC PC, PC, R0, LSL#2 B invalid .table B zero B one B two .endoftable
My personal favourite method is the latter, but both will have the desired effect.