よもぎのメモ帳

備忘録的な感じで技術的なことをストックしていきます。

よもぎのための「レジスタのまとめ」

れじすたっておいしいの?

レジスタと言われても、それがどういうものかを知っている人は人口の1%程度だと思います。*1 もしもあなたの周囲で8割以上が理解しているのなら、人付き合いを見直したほうがいいと思いますね。*2*3

以下はWikipediaからの引用

レジスタ (コンピュータ) - Wikipedia

レジスタ(register)はコンピュータのプロセッサなどが内蔵する記憶回路で、制御装置や演算装置や実行ユニットに直結した、操作に要する速度が最速の、比較的少量のものを指す。

ここで気をつけたほうがいいと思うのは、レジスタは記憶装置というよりも演算装置の一部である、ということ。

記憶装置の説明の比喩として、”本”をデータに見立て、”本棚”がHDDやSSDなどの補助記憶装置、”机”がメモリなどの主記憶装置のようなものである、という説明があると思います。 ここに本を開く”手のひら”という場所を追加してみると、これにはCPU内部のキャッシュのようなもの*4。 そして本を読んでるときの内容を記憶する”脳”。これこそがレジスタ、ではないでしょうか。

ばしょ ひゆ はやさ おおきさ
レジスタ 速い 小さい
キャッシュ 手のひら
メモリ(主記憶装置)
HDD/SSD(補助記憶装置) 本棚 遅い 大きい

このレジスタに読み込んだものに対して、CPUの演算処理が働く、みたいな感じでしょうか。直接いじることが多いと思われます。

アセンブリ言語でみると使われているのがみえる。*5gccアセンブリ言語を見たいときには

$ gcc -S hogehoge.c

これでhogehoge.sファイルと言うかたちで出力されるので、これをテキストエディタなどで見ればよし。


x86あーきてくちゃぁ

x86アーキテクチャ、聞いたことあるかと思います。これが今現在一般的なマイクロプロセッサの命令セットアーキテクチャで、一般的には32bitだと思います。これを64bitに拡張したものをx86-64だとかx64とか言います。

もともと、16bit CPUのIntel 8086での命令セットを32bit CPUのIntel 80386*6で32bitに拡張したものです。64bitに拡張したのはAMDさんらしいけど。

この記事では、このx86アーキテクチャ(あるいは、x86-64)に基づいた説明をしていきますね。


れじすたのせつめい

いろいろあるレジスタについて、グループ分けしながら。といってもこの分け方は色々あるので、お世話になっているハリネズミ*7に従っていきます。

汎用レジスタ

汎用レジスタはどんな使い方でもできるものですが、通例というものがあります。

name なまえ つかわれかた
EAX アキュームレータレジスタ 演算の結果
ECX カウンタレジスタ カウント(ループ回数など)
EDX データレジスタ 演算に用いるデータ
EBX ベースレジスタ アドレスのベース値
ESI ソースインデクスレジスタ データの転送元(データ転送命令)
EDI デスティネーションインデックスレジスタ データの転送先(データ転送命令)

ちなみにこのEっていうのは32bitを表す接頭語みたいに考えるといいと思います。

特殊レジスタ

専用の用途があるということですが、たとえばx64だと汎用レジスタとしてつかえるものもあるみたい

name なまえ つかわれかた
EBP ベースポインタレジスタ 現在のスタックフレームにおける底のアドレスの保持
ESP スタックポインタレジスタ 現在のスタックトップのアドレスの保持
EIP インストラクションポインタレジスタ 次に実行するアセンブリ命令のアドレスを保持

EFLAGSレジスタ

演算の結果による影響を保持したり、プロセッサの状態に格納するレジスタで、各bitにそれぞれの役割があります。プログラミングでもflagを立てて条件分岐に役立てるとか、やったことあると思う。x64だとRFLAGSレジスタみたい。

x86,x64では18bitのflagがあるけれども、CTFで比較的使うらしいものを選びます。ちなみにflagで用いられないbitは予約されている(reserved)で変更されないべき。

name なまえ bit つかわれかた
CF キャリーフラグ 0 演算でキャリー*8|orボロー*9でセット
ZF ゼロフラグ 6 演算で0になったときにセット
SF 符号フラグ*10 7 演算で負になったときにセット
DF 方向フラグ*11 10 ストリームの方向を制御
OF オーバーフローフラグ 11 符号付き算術演算でオーバーフローしたときにセット

セグメントレジスタ

メモリ管理のために区切った領域がセグメント*12。セグメントの先頭のアドレスを格納しているみたいです。

name なまえ つかわれかた
CS コードセグメントレジスタ コードセグメントのアドレス
DS データセグメントレジスタ データセグメントのアドレス
SS スタックセグメントレジスタ スタックセグメントのアドレス
ES エクストラセグメントレジスタ エクストラセグメント(1つめの追加セグメント)のアドレス
FS Fセグメントレジスタ エクストラセグメント(2つめの追加セグメント)のアドレス
GS Gセグメントレジスタ エクストラセグメント(3つめの追加セグメント)のアドレス

Eの次だからF,Gという命名の適当さは好きです。セグメントよくわかっていないのでおいおい


こまかいよびかた

汎用レジスタや特殊レジスタには、そのレジスタ内でも特定の場所にたいして呼び方があります。

具体的には、

  • RAX->64bitでの基本長
  • EAX->32bitでの基本長。64bitの場合、下位32bitを表す
  • AX->下位16bitを表す
  • AH->AXの中で上位8bitを表す
  • AL->AXの中で下位8bitを表す

こんな感じになっています。x86がもともと16bitを拡張したものと言う感じが伝わってきますね。なお、AHにあたるものがESI,EDI,EBP,ESP,EIPにはないです。

つぎの画像を参考にしてもらえるとわかってもらえるんじゃないかな。

f:id:y0m0g1:20180227003944j:plain f:id:y0m0g1:20180227003953j:plain


あとがき

だいたいこんな感じで一通りだと思います。間違っている所ありましたら教えてください

追記

追記1: EIPに対して、IPLというのは存在しないみたいです x86 - Wikipedia

参考

X86アセンブラ/x86アーキテクチャ - Wikibooks

Assembly Programming on x86-64 Linux (04)

プログラミングノート - x86

FLAGS register - Wikipedia


*1:ソースはありません

*2:むしろ残りの2割の付き合いを無くしていけとも

*3:真に受けないで

*4:補助記憶装置→主記憶装置→キャッシュの順でデータは行くと思うのであまり正しくない比喩かも

*5:まだ経験が浅いので、らしいとつけたい

*6:i386 ってやつです

*7:セキュリティコンテストチャレンジブックのこと

*8:桁上り

*9:桁借り

*10:サインフラグ

*11:ダイレクションフラグ

*12:よくわかっていない