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

x86アーキテクチャは8個の汎用レジスタ (GPR) と6個のセグメントレジスタ、1個のフラグレジスタ、1個の命令ポインタを持っている。
x86アーキテクチャ

64ビットCPUでは、さらに上述以外の補助的なレジスタもあるが、とりあえず上述のレジスタが基本的なので、上述のレジスタについて説明する。
x86アーキテクチャ

汎用レジスタのうち、特に重要な8個には、下記のような名前がついている。また、その8個のレジスタの使用目的は下記の様に規定されている。
x86アーキテクチャ

インテルの用意している命令コマンドの中には、特定のレジスタを対象にしたものがあるので、上述のレジスタの規約を守らなければならない。
x86アーキテクチャ

たとえばintelが用意するアセンブラコマンドの enter 命令は、対象レジスタがebpレジスタとespレジスタだと規定されている事が、2004年のデベロッパーマニュアルで読み取れる(『中巻A:命令セット・リファレンスA-M』3-217)。
x86アーキテクチャ

反対意見もあり、一説では、上述のレジスタは他の用途にも使えるともいう言説を紹介している文献もあるが、しかし当のインテル社自体、いくつかの命令コマンドの対象を特定のレジスタに適用しているので、他の用途に使うのはあまり推奨されないだろう。
x86アーキテクチャ

実際、一般的な入門書では、上述のような用途(たとえばEAXはアキュムレータに使うなど)で使うのが、推奨されている。
x86アーキテクチャ

さて、これら目的の規定されたレジスタとは別に、特に目的の規定されていないレジスタがあり、R8 から R15 までの番号のレジスタも汎用レジスタである、たとえば一時的な値の格納に使われたりするレジスタである。主に64ビットCPUで、R8 〜 R15 が追加されている。 また、これら R8 〜 R15 には特に目的は規定されておらず、任意の目的に使用することができる。
x86アーキテクチャ

ただし、ABIの規定により、R10がCPUのソフトウェア割込みであるシステムコールに使われるなど、いくつかの取決めがある。
x86アーキテクチャ

命令ポインタ(RIP/EIP/IP)とフラグレジスタ(dflags, eflags)は、(8個の)汎用レジスタではない。命令ポインタなどについては、別の節で説明する。
x86アーキテクチャ

汎用レジスタの最初の4個は、4通りのアクセスの仕方ができる。
x86アーキテクチャ

64ビットCPUにおける「EAX」とは、RAXに使っているレジスタの下位32ビットのことである。けっして、RAXレジスタとは別にEAXレジスタが用意されているわけではない。
x86アーキテクチャ

なので、上述の一覧では32ビット「アクセス」のように言っているわけである。
x86アーキテクチャ

同様に、64ビットCPUではRAXレジスタの下位16ビットを「AX」と読んでいる。
x86アーキテクチャ

RAX以外のRCXやRDXも同様である。RCXの下位32ビットがECXであり、下位16ビットがCXである。
x86アーキテクチャ

なお、現代的なCPUでは、さらに128ビット用のレジスタ(XMM0 〜 XMM15)も用意されているが、しかし入門的でないので128ビット用レジスタについては本ページでは説明を省略する。
x86アーキテクチャ

8ビットアクセスの命令は、昔のintel 8008 の命令幅が8ビットだった時代の名残り(なごり)である。
x86アーキテクチャ

8ビットアクセスのALなどの末尾のLは、下位(Low)のこと 。AHなどの末尾HはHighのこと。
x86アーキテクチャ

8ビットを基準に、拡張 extended したので、16ビットには「X」(extend の2文字目)をつけてAX,CX,DX,などのように言うようになった(もともと8ビットでは A,C,D などと呼んでいた.。ALやAHなどのL,Hは、その拡張のころにつけられた末尾)。
x86アーキテクチャ

さらに32ビットに拡張する際、Extend の1文字目eを付けて区別して、eax,ecx,edx のように呼ぶようになった。
x86アーキテクチャ

rax などの頭文字 r は、64ビット用のこと。
x86アーキテクチャ

最後の4個は、2通りのアクセス方法がある。
x86アーキテクチャ

セグメントとは、メモリ空間について「先頭アドレスとサイズ」を定義し一纏めにした領域(いわば配列)のようなものであり、用途(スタック領域を指し示す・コード領域を指し示す・データ領域を指し示す)毎に、そのメモリ領域の先頭を示すポインタであるのがセグメントレジスタである(これはリアルモードの場合、プロテクトモードではセグメントディスクリプタが入る)。
x86アーキテクチャ

6個のセグメントレジスタは以下のとおりである。
x86アーキテクチャ

ほとんどの現代的なオペレーティングシステム(LinuxやMicrosoft Windowsなど)で動くほとんどのアプリケーションは、ほとんど全てのセグメントレジスタが同じ場所を指し示すメモリモデルを採用しており(代わりにページングを使用している)、事実上これらの使用は無効になっている。 FSやGSはこの決まりの例外となっており、スレッド独自のデータを指し示すのに使われる。
x86アーキテクチャ

EFLAGSは1個の32ビットレジスタで、操作の結果やプロセッサの状態の格納と制御のための判断材料として使用される。
x86アーキテクチャ

これらのビットの名前は、以下のとおりである。
x86アーキテクチャ

ビットの名前が0または1になっているものは予約されているので、変更されるべきではない。
x86アーキテクチャ

命令ポインタ (EIP) は、分岐が起きない前提で、次に実行する命令のアドレスを保持している。
x86アーキテクチャ

EIPはcall命令の直後にのみ読むことができる。
x86アーキテクチャ

x86アーキテクチャはリトルエンディアンであり、16bitからなるワードや32bitからなるロングワードデータなどのマルチバイトデータの値は最下位バイトから順に書き込まれる。 これはバイト単位の順序についてであり、ビット単位の順序についてではない。
x86アーキテクチャ

つまり、32ビットの値である0xB3B2B1B0は(以下0xは16進数を示す)、x86システムのメモリ上では以下のように表現される。
x86アーキテクチャ

同様に、32ビットの倍精度ワード0x1BA583D4 は、メモリ上では以下となる。
x86アーキテクチャ

したがって、メモリをバイト単位で表示すると0xD4, 0x83, 0xA5, 0x1Bのように見える。
x86アーキテクチャ

2の補数というのは、2進数で負の整数を表現する標準的な方法である。 数値の符号を変えるには、全てのビットを逆にし、1を足せば良い。
x86アーキテクチャ

00012は10進数での1である。
x86アーキテクチャ

11112は10進数での-1である。
x86アーキテクチャ

x86の各機械語は、動作の対象として(オペランドと呼ぶ)、上記レジスタ、メモリ空間あるいは数値(即値と呼ばれる)にアクセスするが、その方法は命令により限定されている。
x86アーキテクチャ

アドレッシングモードとは、オペランドにアクセスする方法を示す、名称である。
x86アーキテクチャ

あるいは、
スタック

スタックとは後入れ先出し方式のデータ構造で、データはスタックに上からプッシュされ、入れた順序を逆にポップしてくる。
スタック

AXの値をスタックの最上部にプッシュするとする。スタックは$006Aという値を保持している。
スタック

BXの値を同様にスタックにプッシュする。スタックは$006Aと$F78Aの値を保持している。
スタック

同様にCXの値もプッシュすると、スタックは$006A、$F79A、$1124を保持することとなる。
スタック

何かをする。関数はレジスタを使わないものとする。
スタック

スタックに最後にプッシュされた要素をポップさせてCXに読み込む。CXの値は$1124となり、スタックには$006A、$F79Aが保持されている。
スタック

スタックの最上部の要素をポップさせてBXに読み込む。BXの値は$F729となり、スタックには$006Aしかなくなる。
スタック

スタックの最上部の要素をAXに読み込む。AXの値は$006Aとなり、スタックは空となる。
スタック

スタックは通常、引数を関数や手続きに渡すために使われる。また、call命令が使われた時に制御フローを監視するためにも使われる。 その他のスタックのよくある使い方は、一時的にレジスタの値を保存しておくことである。
CPUの動作モード

2010年代の現代のパソコンのアーキテクチャも、深層部は ほぼ16ビット時代の名残り(なごり)のままである。
CPUの動作モード

市場のパソコンのアーキテクチャは事実上、昔からの技術のツギハギになっており、16ビットCPUの名残のモード(「リアルモード」)の上に32ビットCPUのモード(「プロテクトモード」という)を付け加え、さらにその上に64ビットCPUのモードを付け加えるという、ツギハギのような状態になっているのである。
CPUの動作モード

コンピュータの電源投入の起動直後、CPUはまず(16ビット時代の名残りである)リアルモードを実行し、それを土台に(32ビット時代の名残りの)プロテクトモードに切り替え、必要ならさらに64ビット時代のモードに切り替える、という仕組みになっている。
CPUの動作モード

リアルモードとは、16ビットCPUの時代のモードである。
CPUの動作モード

この16ビットCPU時代のモードの構造が比較的に単純だからか、2010年代の今でもOSなどの深層部に残っており、ブート起動直後に動作するのは実は16ビット時代のモードである。この、ブート直後などの16ビット時代のモードのことを「リアルモード」とIT業界では呼んでいる。
CPUの動作モード

リアルモードは、仮想メモリをサポートしていないし、マルチタスク処理をサポートしていない。
CPUの動作モード

リアルモードは元々の(1978年の)インテル8086プロセッサからの遺産である(※ 1980年代の「80386」でなく「8086」。80386とは別物)。一般的にはこれについて何も知る必要はない ←(いや、アセンブラの技術者なら知る必要あるだろ。)(MS-DOS用のプログラムを書いたり、BIOSから直接実行されるブートローダを書いたりしない限りは)。
CPUの動作モード

インテル8086はメモリにアクセスするのに20ビットのアドレスを使っていた。しかし、プロセッサ自体は16ビットであったため、インテルは、20ビットのアドレッシングスペースを16ビットワードに割り当てる方法を用意するという、アドレッシングスキームを発明した。現在のx86プロセッサは、後方互換性のため、若干の違いはあるがこの8086の動作を真似た動作モードである、リアルモードで起動する。
CPUの動作モード

リアルモードでは、セグメントレジスタとオフセットレジスタの両方が最終的なメモリアドレスを得るために使われる。セグメントレジスタの値は、16倍(つまり左に4ビットシフト)し、オフセットが加算されてメモリアドレスを得る。これによって1MBのスペースが使えるようになった。しかし、このアドレッシング方法によって、セグメントレジスタの値をその最大値である0xFFFFにすることによって、1MBを超える領域にアクセスできるようになった。 8086と8088では、このエリアへの全てのアクセスによってメモリを使い切ることとなるが、80286以降では、この1MB以降に最大65520バイトまで、A20アドレスラインを有効化することにより、同様な方法でアクセスすることができる。参照: A20ゲートの物語
CPUの動作モード

リアルモードのセグメントとプロテクトモードでのマルチセグメントメモリモードに共通するの利点は、全てのアドレスがあるアドレスから相対的な位置として与えられるということである(これをセグメントベースアドレスと呼ぶ)。プログラムはそれ自身のアドレススペースを持つことができ、完全にセグメントレジスタを無視することができる。そして、プログラムを実行するためにはポインタを移動させる必要がない。プログラムは近くにあるコールを実行し、同じセグメント内でジャンプする。そしてデータは常にセグメントベースアドレスから相対的にある(リアルモードアドレッシング方法では、セグメントレジスタに格納された値から計算される)。
CPUの動作モード

これはDOSの*.COMフォーマットがしていることである。ファイルの内容はメモリに読み込まれ、そのまま実行される。しかし、リアルモードセグメントは常に64KBであるため、COMファイルは64KBより大きくすることができない(実際には65280バイトまで可能であるが、DOSはセグメント最初の256を管理用に使う)。長い間、これは問題にはならなかった。
CPUの動作モード

LinuxやWindowsといった現代的なオペレーティングシステムでプログラミングする場合には、基本的にはフラット32ビットモードでプログラミングをする。 全てのレジスタはアドレッシングに使うことができ、完全に32ビットのレジスタを16ビットレジスタの代わりに使うことで、より効率的になる。 加えて、セグメントレジスタは一般的にはフラットモードでは使われず、これに触れるのは悪い考えであるといえる。
CPUの動作モード

(未執筆)