BAKの日記: OpenBlockS266 めも 2
ジャンプとブランチ
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 レジスタがあまりにも気色悪かったので,この話はこういう感じで締めることにする.
branch (スコア:1)
えっと、解説 [tudelft.nl]みると、、ba, bla [tudelft.nl], 、bca, bcla [tudelft.nl]が絶対アドレスですね
# 「読み下し」書いてなかったら勘違いするとこだった
Re:branch (スコア:1)