アセンブリを読むにあたって、レジスタの役割がよーわからんかったので自分なりにまとめてみる。
言葉が違ったりするので厳密な定義などが知りたい場合は他サイトで。
レジスタには汎用レジスタやインデックスレジスタなど、色々種類がある上に同じレジスタでもサイズごとに名前が異なるため、おびただしい量になる。
EAX/AX/AL/AH/ECX/CX/CL/CH/EDX/DX/DL/DH/EBX/BX/BL/BH・・・・・
こんなの見てられないので、見分け方を身に着ける。
それぞれで〇の中身になる文字、〇以外のやつら(以下、「何か」という。)
の意味をまとめてみる
R〇X・E〇X・〇X・〇L・〇Hのパターン
データの格納に用いるレジスタ達
〇 | 意味 | 役割 |
---|---|---|
A | アキュムレータレジスタ | 演算時の計算結果が格納される |
B | ベースレジスタ | 指標レジスタとして使用される |
C | カウンタレジスタ | ループ命令とかのカウンタに使用される |
D | データレジスタ | 計算するときや、インプット・アウトプット操作に使用される |
ABCDで覚えやすい。汎用レジスタって名前だけあって結構使われる
何か | 意味 |
---|---|
RX | 64bitアクセス |
EX | 32bitアクセス |
X | 16bitアクセス |
L | 8bitアクセス |
H | 8bitアクセス |
雰囲気でわかるだろうが、RXの64bitアクセスはx64で使われる。 8bitが2つあるが、HighとLowで前半8bitと後半8bitという意味らしい
R〇I・E〇I・〇Iのパターン
ストリーム操作で使うらしい。よく意味はわからないので意味は調べたまま。
〇 | 意味 | 役割 |
---|---|---|
S | ソースインデックス | ストリーム操作でのソースへのポインタとして使用される |
D | デスティネーションインデックス | ストリーム操作でのデスティネーションへのポインタとして使用される |
むずかしそう。
何か | 意味 |
---|---|
RI | 64bitアクセス |
EI | 32bitアクセス |
I | 16bitアクセス |
ここでも、RIの64bitアクセスはx64で使われる。
サイズについては単純で、汎用レジスタと似てるのでわかりやすい。
後述するが、インデックスレジスタの「何か」達は特殊レジスタと同じ
R〇P・E〇P・〇Pのパターン
ポインタとして使用される。
〇 | 意味 | 役割 |
---|---|---|
B | ベースポインタ | スタックのトベースを指し示す |
S | スタックポインタ | スタックのトップを指し示す |
I | インストラクションポインタ | 命令ポインタ。分岐が起きない前提で次の命令のアドレスを保持 |
スタックポインタと命令ポインタ。
前述したとおり、インデックスレジスタの「何か」と同じだが、
インストラクションポインタだけはEIPだけ。
〇Sのパターン
メモリ空間について「先頭アドレスとサイズ」を定義し一纏めにした領域のようなものがセグメント。
用途ごとにそのメモリ領域の先頭を示すポインタであるのがセグメントレジスタである
〇 | 意味 | 役割 |
---|---|---|
S | スタックセグメント | スタックへのポインタ |
C | コードセグメント | コードへのポインタ |
D | データセグメント | データへのポインタ |
E | エクストラセグメント | 追加データへのポインタ |
F | Fセグメント | さらに追加のデータへのポインタ |
G | Gセグメント | さらにさらに追加のデータへのポインタ |
SCDはそのまま。EはExtra、F,GはABCでEの続き。「何か」はない。
R8~R15の8個。
x64で追加された汎用レジスタ。引数や数値の保持などに使用される
次は、ついでに関数を呼び出すときのレジスタの使われ方を調べてみた。x64とx86で呼び出し方が違うらしい。
x86のプログラムの関数の引数はスタックを使用するらしい 例として、2つ引数をとるadd関数をadd(3,4)として呼び出してみる。アドレスは適当だ。
アドレス | 命令 | 引数1 | 引数2 | コメント |
---|---|---|---|---|
0100 | push | 4 | 第2引数をpush | |
0105 | push | 3 | 第1引数をpush | |
010A | call | add | add(3,4) | |
010F | hoge | fuga | 続き。直後は引数の後処理とかが入ることが多い |
第2引数、第1引数の順番でpushする様だ。次はcall実行時のスタックの様子を見る
アドレス | データ | コメント |
---|---|---|
0x9FF0 | 00000000 | |
0x9FF4 | 0000010F | [add]call戻り先 |
0x9FF8 | 00000003 | [add]引数1 |
0x9FFC | 00000004 | [add]引数2 |
0x1000 | 00000000 | [add] |
こんな感じ。今回はレジスタに注目したかったのでそろそろx64の引数を見てみる。
x64だと第1~6引数はレジスタを使用し、第7引数以降はスタックを使用するらしい。 スタックの使い方はx86と同じだと思うのでレジスタのみに視点を当てる。ここで、レジスタ達は64bitサイズの表記だ
レジスタ | 役割 |
---|---|
RAX | 戻り値 |
RDI | 第1引数 |
RSI | 2 |
RDX | 3 |
RCX | 4 |
R8 | 5 |
R9 | 6 |
RAX以外が今までの役割と違うことに困惑する。そのまま覚えることは嫌いなので調べた。 引数の扱いが違うのが出てきて涙目になって終わった。
x64 software conventions #Register volatility and preservation
x64の引数の規則性がわからない。けど、だいたいcall命令の直前にpushされてるようなので、慣れでどうにかして行きたい