パスワードを忘れた? アカウント作成
359305 journal

BAKの日記: OpenBlockS266 めも 2

日記 by BAK

ジャンプとブランチ

CPU 一般の用語として

  • 「ジャンプ」とは,~のアドレスにプログラムの制御を移す,ということ
  • 「ブランチ」とは,現在の(正確にはちと違うが)実行アドレスから~だけ前(または後ろ)のアドレスにプログラムの制御を移す,ということ

を指すことが多いようである.上記のジャンプのことを「絶対ジャンプ」,ブランチのことを「相対ジャンプ」と言うこともある.

が,PowerPC の場合,

  • 相対ジャンプは b, bl, bc, bcl
  • 絶対ジャンプは ba, bal, bca, bcla

というニーモニックになっている.読み下しとしては

  • b は branch
  • c は conditional
  • l はおそらく link
  • a はおそらく absolute

の意味である.絶対ジャンプも相対ジャンプも全てブランチ,なのである.ちょっとびっくり.

あ,link というのは,RISC 系の CPU でのサブルーチンコールです.RISC 系の CPU では,明示的なスタックが無いので,サブルーチンコールは戻り先のアドレスを特定のレジスタに退避させてからジャンプします.これを link と呼ぶことが多いようです.

で,話を元に戻すと,これらの命令でのジャンプ先は全てイミディエイト値で指定される.つまり,「レジスタ相対」みたいなアドレッシングは(これらの命令では)無い.

RISC 系の CPU はオペコード・オペランドを合わせた命令長が固定のものが普通である.PowerPC でも命令長は 32bit の固定長である.ここにオペコードとオペランドがエンコーディングされるので,これらの命令ではどう頑張っても 32bit のアドレス空間の任意の位置へジャンプする命令は記述できない.

以下の例は,linux/arch/ppc/boot/common/relocate.S にあるコードである.

                /*
                  * Start at the begining.
                  */
                li r9,0x0000
                mtlr r9
                blr

r9 に 0x00000000 という値をロードした後,これを LR レジスタ(リンクレジスタ)に転送し,LR レジスタのアドレスにジャンプしている.

LR レジスタとは,サブルーチンコール時の戻り先アドレスを保持しているレジスタである.つまり,ここでは強引にこのアドレスを書き換えてサブルーチンからの復帰を行うことにより,任意のアドレスにジャンプしていることになる.

これはあまりにもド汚すぎるので,他の方法はないのか,と,gcc にお伺いを立てることにする.以下のプログラムを -O2 オプションでコンパイルし,逆アセンブルする.

jump ( void )
{
                void *f = (void *)0xfffffffc;

                goto *f;
}

あー,プログラム自体がド汚いのは勘弁してね.

すると,こういう結果が得られる.

huga.o: file format elf32-powerpc

Disassembly of section .text:

00000000 <jump>:
      0: 38 00 ff fc li r0,-4
      4: 7c 09 03 a6 mtctr r0
      8: 4e 80 04 20 bctr

r0 にイミディエイト値をロードし,これを CTR レジスタに転送,CTR レジスタのアドレスにジャンプ,ということである.

で,CTR レジスタとは何ぞや,というと,「ループのカウント値(後何回回るか)という値の保持,もしくはジャンプ先アドレスの保持」という,とても気色の悪い役回りのレジスタである.

ちなみに,同じことを MIPS でやってみると,こんな感じになる.

huga.o: file format elf32-tradlittlemips

Disassembly of section .text:

00000000 <jump>:
      0: 3c1c0000 lui gp,0x0
      4: 279c0000 addiu gp,gp,0
      8: 0399e021 addu gp,gp,t9
      c: 2402fffc li v0,-4
    10: 00400008 jr v0
                ...

MIPS の場合,遅延分岐があるので,正確には 0x14 に nop が入る.また,前の3命令はサブルーチンコール後の前処理で,ジャンプ自体とは無関係である.

MIPS の場合,「汎用レジスタが示すアドレスにジャンプ」という命令があるので,こんな感じに記述できるのである.

CTR レジスタがあまりにも気色悪かったので,この話はこういう感じで締めることにする.

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • by umq (4421) on 2003年05月16日 15時19分 (#317115) 日記

    上記のジャンプのことを「絶対ジャンプ」,ブランチのことを「相対ジャンプ」と言うこともある.
    が,PowerPC の場合,
    • 絶対ジャンプは b, bl, bc, bcl
    • 相対ジャンプは ba, bal, bca,bcla

    というニーモニックになっている.読み下しとしては
    • b は branch
    • c は conditional
    • l はおそらく link
    • a はおそらく absolute

    の意味である.絶対ジャンプも相対ジャンプも全てブランチ,なのである.ちょっとびっくり.


    えっと、解説 [tudelft.nl]みると、、ba, bla [tudelft.nl], 、bca, bcla [tudelft.nl]が絶対アドレスですね
      # 「読み下し」書いてなかったら勘違いするとこだった
typodupeerror

私はプログラマです。1040 formに私の職業としてそう書いています -- Ken Thompson

読み込み中...