ネゲート
mvn r0, #1 ; r0 <- -2mvn r1, #2 ; r1 <- -3
cmn r0, #1 ; if r0 == -1
bne xxx
; r0=-1
関数定義
function
func_entry:
stmfd r13!, {<registers>,r14}
:
ldmfd r13!, {<registers>,pc} ; pop and return
func_entry:
: ; r0-r3以外使わない場合
:
mov pc, lr ; return
func_entry:
: ; r0-r3以外使わない場合(Thumb使用、最近のARMはこうするべき)
:
bx lr ; return
func_entry:
stmfd r13!, {lr} ; 他の関数を呼ぶ場合
:
bl other_func
:
ldmfd r13!, {pc} ; return
mrsは、フラグレジスタ(ステータスレジスタ(s)を汎用レジスタ(r0))へ転送
msrは、その逆
mrs r0, cpsr
orr r0, r0, #0x80
msr cpsr_c, r0
レジスタ一覧
r0-r15,cpsr
spsr
※spsrは、cpsrのsaveレジスタ
- alias(レジスタ別名呼称)
r0=a1 argument:
r3=a4
r4=v1 register variable
:
r9=v6, rfp real frame pointer
r10=sl stack limit
r11=fp argument pointer
r12=ip temporary work space
r13=sp stack pointer
r14=lr link register
r15=pc program counter
例外発生時のレジスタ(svc:スーパバイザモード以外は一部のレジスタはバンク切替される)
cpsr[4:0]priority mode independent reg
0x10 - user
0x1f - system
0x13 - svc r13-14, spsr
0x17 5 abort r13-14, spsr
0x1b 6 undef r13-14, spsr
0x12 4 irq r13-14, spsr
0x11 3 fiq r8-r14, spsr
reset 1
dabort 2
↑ SVCモードではr13(sp)とr14(lr),spsrは他モードと独立して存在するということ
cpsr: bit7=irq (1=disable)
cpsr: bit6=fiq (1=disable)
exception occured.
↓
change processer mode
↓
r14 <- return (befor exception) address
↓
spsr <- cpsr cpsrはspsrに保存されるものの多重割込みを使用する場合自分でPushしたりする必要があるので注意
↓
cpsr |= 0x80 // disable irq
↓
FIQ ?
cpsr |= 0x40 // disable fiq
pc <- exception vector address
↓
transaction exception handler
//
--
movs pc, lr ; pc <- lr, spsr -> cpsr
--
割込み発生時の割込みルーチンエントリ時、戻り値lrは再開番地と異なる。以下。
undef/swi
:
movs pc, lr
fiq/irq;
:
subs pc, lr, #4
prefetch:
:
subs pc, lr, #4
dabort:
:
subs pc, lr, #8
interrupt(stack use):
sub lr, lr, #4
stmfd r13!, {r0-r7, lr}
:
ldmfd r13!, {r0-r7, pc}^
^ はmovsと同様 spsr->cpsrやってくれる
多重割込みの場合、spsrは自分でPushする必要があるから
interrupt:
msr cpsr, #(CPSR_SVC|CPSR_IRQ_BIT)
stmfd sp!, {r0-r3, ip, lr, pc} /* pcはダミー */
msr cpsr, #(CPSR_IRQ|CPSR_IRQ_BIT)
sub r0, lr, #4
mrs r1, spsr
msr cpsr, #(CPSR_SVC|CPSR_IRQ_BIT)
str r0, [sp, #0x18] /* 戻り番地をダミーpcの保存スタック位置へ */
stmfd sp!, {r1} /* spsrをスタックに保存 */
mov lr, sp /* この時点のスタックを復帰のため取得 */
: