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