Skip to content

Instantly share code, notes, and snippets.

@y0d3n
Last active November 5, 2019 21:41
Show Gist options
  • Save y0d3n/9fe5eca5c0761c893bbcd5d3c875c523 to your computer and use it in GitHub Desktop.
Save y0d3n/9fe5eca5c0761c893bbcd5d3c875c523 to your computer and use it in GitHub Desktop.
レジスタの見分け方を身に着ける

アセンブリを読むにあたって、レジスタの役割がよーわからんかったので自分なりにまとめてみる。
言葉が違ったりするので厳密な定義などが知りたい場合は他サイトで。

レジスタ

レジスタには汎用レジスタやインデックスレジスタなど、色々種類がある上に同じレジスタでもサイズごとに名前が異なるため、おびただしい量になる。

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の引数

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の引数

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されてるようなので、慣れでどうにかして行きたい

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment