アドレシング・エンディアン
現在、CSの勉強のために、コンピュータアーキテクチャ (電子情報通信レクチャーシリーズ)を読んでいる。
アドレシング(addressing)とは、データや命令が格納されている場所(アドレス)を特定することである。典型的には、命令からメモリの番地(アドレス)を生成することである。これまでも命令でアドレスを指定してきたが、今回アドレスの指定方法についてまとめておく。
MIPSアドレシング・モード
- 即値アドレシング(immediate addressing)
- レジスタ・アドレシング(register addressing)
- ベース相対アドレシング(base addressing)
- PC相対アドレシング(PC-relative addressing)
- (PC + 4)とオペランド部に指定した定数との和によってメモリの位置(アドレス)を示す
- 現在の命令アドレス(PC)ではなく、次の命令(PC + 4)のアドレスを基準にして相対アドレシングを行う
- 命令のアドレスは常に4の倍数である。(メモリはバイト単位であり、1命令は32bit、4Byteであるため、命令のアドレスは常に4の倍数となる。)4の倍数にするためには、2ビット左にシフトする。
- 分岐命令(ex. beq $s0, $s1, Exit)など
- 擬似直接アドレシング(pseudodirect addressing)
- 命令中の26ビットとPCの上位ビットを連結したものがジャンプ・アドレスとなる
- 命令のアドレスは常に4の倍数であるため、2ビット左にシフトする
- 無条件ジャンプ(ex. j Exit)
32ビットの即値のオペランド
MIPSの全ての命令の長さは32ビットである。そのため、1命令で即値は16ビットでしか指定することができない。定数は小さいことが多いので、ほとんどが16ビットで収まる。しかしながら、時には定数の長さが16ビットを超える場合もあると思う。その場合に備えて、MIPSの命令セットには load upper immediate lui
命令が用意されている。この命令を使うことで、定数の上位16ビットをレジスタに入れることができる。
例題:MIPSアセンブリコード
下記の32ビットの定数をレジスタ $s0 にロードするMIPSアセンブリコードを示せ。
0000 0000 0011 1101 0000 1001 0000 0000
32ビットの定数を、上位16ビットと下位16ビットに分離する。
- 上位
0000 0000 0011 1101
= 10進数の61
- 下位
0000 1001 0000 0000
= 10進数の2304
lui
で上位16ビットを$s0にロードする。その後、ori
(or immediate)で$s0に下位16ビットを追加する。
lui $s0, 61 # 0000 0000 0011 1101 0000 0000 0000 0000 ori $s0, $s0, 2304 # 0000 0000 0011 1101 0000 1001 0000 0000
エンディアン
一般に、メモリのアドレシングの単位はバイトである。すなわち、メモリアドレスは、メモリの中の1バイトを特定するものである。
例えば、0x12345678というデータ語があった場合に、これをメモリのAddXに書き込むことを考える。1バイト単位に分割して書き込む際に、書き込む順番によって、2つのパターンが考えられる。
- 左から、0x12, 0x34, 0x56, 0x78
- 右から、0x78, 0x56, 0x34, 0x12
このバイト並びの方式をエンディアンと呼ぶ。
ビックエンディアンでは、データ語のアドレスA00を最上位バイト(MSB:Most Significant Byte)に格納し、左から順番に格納していき、アドレスA03を最下位バイト(LSB:Least Significant Byte)に格納する。
反対に、リトルエンディアンでは、データ語のアドレスA00をLSBに格納し、右から順番に格納していき、アドレスA03をMSBに格納する。
エンディアンはCPUによって決まっている。PowerPCなどはビッグエンディアン、Intel系などはリトルエンディアンになっている。また、MIPSなどはどちらにもなることができ、バイエンディアンと呼ばれている。
まとめ
MIPSのアドレシング・モードとエンディアンに関して整理を行った。
ビックエンディアンとリトルエンディアンの言葉の由来は「ガリバー旅行記」らしい。ガリバー旅行記に、卵を丸い方(大きい方)から割る人々(Big Endians)と、尖った方(小さい方)から割る人々(Little Endians)との対立が描かれており、それが由来となっている。