ARM のスタックについて
08 November 2012
Stack のポリシー
まずは一般論から。
Stack Pointer の指している先にデータがあるかないかで以下のように分かれる。
- Full Stack: Stack Pointer は最後に使用された位置を指している
- Empty Stack: Stack Pointer は未使用な最初の位置を指している
また、アドレスが小さくなる方に成長するか、アドレスが大きくなる方に成長するかで以下のように分かれる。
- 下降スタック : メモリアドレスの降順に増加
- 上昇スタック : メモリアドレスの昇順に増加
だから、スタックのポリシー的には 2 X 2 = 4 通りが可能ということになる。
ARM の場合
どれを採用するかは ABI で決められることだが、 ARM では Full & 下降スタックを使うようだ。
ARM の LDM
, STM
命令は表記がいろいろあって、よく忘れるのでメモっておく。
まず表記法として、非スタックアドレッシングとスタックアドレッシングがある。
非スタックアドレッシングは
LDMDA
(Decrement After)LDMIA
(Increment After)LDMDB
(Decrement Before)LDMIB
(Increment Before)STMDA
(Decrement After)STMIA
(Increment After)STMDB
(Decrement Before)STMIB
(Increment Before)
という表記になる。
ARM では Full スタック、下降スタックを採用するというのだから、
push するときには STMDB
命令を使用し、 pop するときには LDMIA
命令を使用しないといけない。
で、常にこういうことを考えるのも面倒なので、スタックアドレッシングの表記も用意されている
LDMFA
(Full Ascending)LDMFD
(Full Desending)LDMEA
(Empty Ascending)LDMFD
(Empty Descending)STMFA
(Full Ascending)STMFD
(Full Desending)STMEA
(Empty Ascending)STMFD
(Empty Descending)
で、非スタックアドレッシングとスタックアドレッシングの関係だが、以下は同じになる。
Non-stack / Stack adressing
LDMDA = LDMFA
LDMIA = LDMFD (= pop)
LDMDB = LDMEA
LDMIB = LDMED
STMDA = STMED
STMIA = STMEA
STMDB = STMFD (= push)
STMIB = STMFA
そういうわけで、 関数のプロローグのよくある
STMDB r13!, {r4-r7, r9, r14}
という命令は
STMFD r13!, {r4-r7, r9, r14}
とも書けるし、さらに簡単に
push {r4-r7, r9, r14}
とも書ける。
!
はオートインデックス指定。
同様に、関数のエピローグでは
LDMIA r13!, {r4-r7, r9, r15}
は
LDMFD r13!, {r4-r7, r9, r15}
とも書けるし、さらに簡単に
pop {r4-r7, r9, r15}
とも書ける。
push
, pop
表記が使えるのは gcc だからかもしれない。(未確認)
blog comments powered by Disqus