計算機システム
II
・第
3
回
2018年 10 月 9 日 今回の内容 3.1 データ転送命令 . . . . 3 – 1 3.2 演算命令 . . . . 3 – 2 3.3 アドレッシングモード . . . . 3 – 7 3.4 付録: Intel 64アーキテクチャ64 bitモードのデータ転送命令と演算命令の概要 3 – 133.1
データ転送命令
CPUの命令セットに含まれる機械語命令の中でも、最も基本となる命令がデータ転送命令です。データ転送命令は、8 bit、16 bit、32 bit、64 bit等の大きさのデータを、特定のレジスタや、メモ
リの特定のアドレスへコピーします。データ転送命令では、その機械語命令のビット列(ビットパ ターン)の一部で、コピーするデータの大きさ(の種別)、データのコピー先となるレジスタやメモ リのアドレスと、コピー元のデータ(そのもの、あるいはそのデータが置かれたレジスタやメモリ のアドレス)を指定します。 機械語命令の操作の対象を、その機械語命令のオペランド(operand)と呼びます。また、その 内、値を読み出すオペランドをソースオペランド(source operand)と呼び、値の書き込み先となる オペランドをデスティネーションオペランド(destination operand)と呼びます。一般のデータ転 送命令では、コピー元となるソースオペランドと、コピー先となるデスティネーションオペランド をそれぞれ1つ指定します1。 メモ アセンブリ言語での表記 データ転送命令も含めて、CPUの機械語命令は単なるビット列でしか ありません。オペランドも、ビット列として機械語命令の一部に埋め込まれているだけです。これ らのビット列は人間にとっては扱いづらいため、機械語プログラムを人間が書き表す際には、アセ ンブリ言語というプログラミング言語が用いられることがあります。アセンブリ言語で1つの機 械語命令を書き表す際には、その機械語命令のビット列の中で、その機械語命令の行う操作を意味 している部分2をニーモニックと呼ばれる文字列(通常は長さ数文字の英文字列)で表し、それに続 けて、そのオペランドが何であるかを適当な約束事に従った記号列で表現します。 1一般のデータ転送命令とは別に、コピー元やコピー先の一方や両方が固定された特殊なデータ転送命令が用意され ていることもあります。その場合、オペランドが1つしかなかったり、全くオペランドがないこともあります。 2 この部分のビット列をオペコード(opcode)と呼びます。機械語命令のビット列の残りの部分が(いくつかの)オペ ランドを表します。
たとえば、Intel 64アーキテクチャのCPUで用いられる、あるアセンブリ言語では、
mov %rax, %rbx
と書くことで、RAXと名付けられた64 bit長のレジスタの内容を、RBXと名付けられた64 bit長の
レジスタへコピーするようなデータ転送命令を表します。movが、このデータ転送命令のオペコー ドのニーモニックで、%raxの部分が、そのソースオペランドがレジスタRAXであることを、%rbx の部分が、そのデスティネーションオペランドがレジスタRBXであることを示しています。 同一の種類のCPUでも、そのためのアセンブリ言語は複数ありますので、そこで使われるニー モニックやオペランドの書き方が異なることに注意が必要です。先の例では、ソースオペランドが 先で、デスティネーションオペランドが後に書かれていましたが、これを逆の順番で書くようなア センブリ言語3も存在します。 メモ ロード命令とストア命令 データ転送命令のソースオペランドは、レジスタの1つであったり、メ モリの特定のアドレスに置かれたデータであったりしますが、メモリ中のデータをレジスタにコ ピーするデータ転送命令をロード(load)命令、逆に、レジスタの値をメモリの特定のアドレスに 書き込むデータ転送命令をストア(store)命令と呼ぶことがあります。アセンブリ言語によって は、この二種類のデータ転送命令を区別して、別系統のニーモニックが与えられる場合もあります。 メモ
3.2
演算命令
CPUに内蔵されている演算回路(ALU)を使って、整数値の四則演算、ビット毎の論理演算、ビッ トシフト、ローテート命令、浮動小数点数値データの四則演算などの計算を行う機械語命令を総称 して演算命令と呼びます。 3 たとえば、Intel社自身が提供しているアセンブリ言語では、デスティネーションオペランドを先に、ソースオペラ ンドを後に書きます。また、ニーモニックも異なります。メモ 状態フラグ CPUが演算命令を実行すると、その計算結果に応じて、次のようなフラグ(flag)と 呼ばれる1 bit長のレジスタが、それぞれ0または1に設定されることがあります。 ゼロ(Zero) 演算結果が0 (つまり、すべてのビットが0)となった サイン(Sign) 演算結果が負(つまり、最上位ビットが1)となった キャリー(Carry) 符号なし整数の演算と見たとき、桁あふれ(最上位ビットか らの繰り上りや繰り下がり)が起った4 オーバーフロー(Overflow) 符号付き整数の演算と見たとき、オーバーフローが起った (つまり、計算結果が符号付き整数で表現できる範囲を外れ てしまった) どのフラグが設定される(影響を受ける)かは、そのCPUの機械語命令ごとに決まっています。主 に整数演算命令やビット演算命令が実行されたときにフラグが設定されますが、データ転送命令が 実行された際にもゼロフラグやサインフラグが設定されるようなCPUもあります。これらの状 態フラグは、次回以降に説明する条件付き分岐命令などで参照され、機械語命令の挙動に影響を与 えることがあります。また、CPUによっては、これらのフラグの値をビット列としてまとめたも のを格納した状態レジスタと呼ばれるレジスタが用意されている場合もあります。そのような場 合、各状態フラグの値を直接参照したり書き換えたりすることも可能です。また、浮動小数点演算 命令を持つCPUは、浮動小数点演算専用の状態フラグあるいは状態レジスタを持っているのが普 通です。 メモ 整数演算命令 多くのCPUで、そのCPUの語長の符号なし整数や符号付き整数の四則演算を行う機械語命令が 用意されています。四則演算を行う機械語命令では、最大3つのオペランドを使用します。たとえ ば、加算命令の場合、足される数aと足す数b の2つのソースオペランドと、加算結果の保存先c 4
CPUによっては、減算の場合は、Carry = 0で最上位ビットでの繰り下がりの発生を意味し、Carry = 1で繰り下
であるデスティネーションオペランドを1つ指定し、C言語風に表現すると c = a + b に相当する仕事を行わせることができます。CPUによっては、2つのオペランドだけを使用し、 a += b に相当する仕事を行う命令が用意される場合もあります。前者を 3オペランド形式(の演算命令)、 後者を 2オペランド形式(の演算命令)と呼びます。2オペランド形式の場合、aは値を読み出すオ ペランドでもあり、値を書き込むオペランドでもありますが、どちらかに分類するときはデスティ ネーションオペランドとするのが普通です。1つのオペランドを指定して、オペランドとなった符 号付き整数の符号を反転する命令が用意されていることもよくあります。 メモ 整数の加算や減算は比較的簡単な論理回路で実現できますが、これに比べて乗算は複雑な仕組み が必要となり、除算では乗算よりもさらに複雑となります。このため、家電製品等への組み込みを 用途とするCPUでは、除算命令や乗算命令を持っていないものも多数あります。このようなCPU
は、語長も短い(4 bitから16 bit)ことが多いので、32 bit等の大きな整数の加減算を含めて、整数 の四則演算を多数の機械語命令を組み合わせた機械語プログラムで実現することになります。
たとえば、8 bitのCPUで32 bit の加算や減算を行うには、8 bitの加算や減算を行う機械語命
令を、下位から上位に向かって8bitずつ4回実行します5。このとき、下位の8 bitの加算で起きた 桁あふれを次の8 bitの計算に反映するため、2つのソースオペランドに加えてキャリーフラグ(0 または1)の値を加算するような加減算命令が用意されているのが普通です6。 メモ 532 bitの乗算や除算を、8 bitの加減算命令の組み合わせで行うには、その少なくとも32倍の機械語命令を実行し なければなりません。 6
このようなキャリーフラグを含めた加減算を行う機械語命令は、64 bit CPUのような語長の大きいCPUにもあ
ビット演算命令 CPUの基本的な演算命令としては、整数演算命令以外に、ビット毎の論理演算、ビットシフト、ビッ トローテートなど、ビット演算命令と総称される命令群があります。整数演算命令と同様、1つの ビット演算命令で、そのCPUの語長までのビット列に対して、ビット毎の論理演算、ビットシフ ト、ビットローテートを行うことができるのが普通です。 メモ ビット毎の論理演算命令 ビット毎の論理演算命令は、C言語の&、|、^演算子に相当する演算 を行う命令で、ソースオペランドとなった2つのビット列に対して、対応するビット同士で論理積
(AND)、論理和(OR)、排他的論理和(XOR)などの論理演算を行い、その結果を同じ順に並べてで きるビット列を演算結果としてデスティネーションオペランドに書き込みます。ビット毎の論理 演算命令も、整数演算命令と同様に、2オペランド形式であったり、3オペランド形式であったりし ます。C言語の~演算子に相当する、オペランドが1つで、ビット列の各ビットを反転する命令も ビット毎の論理演算命令の一種です。 メモ ビットシフト命令 ビットシフト命令は、デスティネーションオペランドとなっているビット列を、 左あるいは右方向にずらします。1 bitだけずらす機械語命令のみが用意されているCPUもあれ ば、何ビットずらすかを(別の))ソースオペランドで指定できるCPUもあります。1 bitの左シフ トの場合、下図(64 bit長のオペランドの例)のように、最下位ビットは0となり、最上位のビット は単に捨てられるか、キャリーフラグにコピーされます。この2つが別の機械語命令となっている 場合もあります。1 bitの左シフトは符号なし、あるいは符号付き整数を2倍にする働きを持ちま す7。 63 0 演算前 1 1 0 1 0 0 · · · 1 1 0 1 演算後 1 0 1 0 0 · · · 1 1 0 1 0 1bit の左シフト 右方向へのビットシフト命令は、通常2種類用意されています。その1つは論理的右シフトと呼 7 その際、桁あふれやオーバフローが起ることがあります。
ばれ、左シフトと左右対称な命令で、最上位ビットは常に0となります。もう1つは算術的右シフ トと呼ばれ、最上位ビットは変更されません。 63 0 演算前 AAU 1 AAU 1 AAU 0 AAU 1 AAU 0 AAU 0 · · · AAU 1 AAU 1 AAU 0 1 演算後 0 1 1 0 1 0 0 · · · 1 1 0 1bit の論理的右シフト 63 0 ?AAU 1 AAU 1 AAU 0 AAU 1 AAU 0 AAU 0 · · · AAU 1 AAU 1 AAU 0 1 1 1 1 0 1 0 0 · · · 1 1 0 1bit の算術的右シフト 1 bitの論理的右シフトは符号なし整数を、算術的右シフトは符号付き整数を、それぞれ1/2 (端 数切り捨て8)にする働きを持ちます。 多ビットのビットシフト命令は、1 bitのビットシフト命令を指定された回数だけ繰り返すのと 同等の操作を行います。この演算は、C言語の<<演算子や>>演算子9に相当します。 メモ ビットローテート命令 オペランドとなったビット列を、最上位ビットと最下位ビットが隣り合っ ているものとみなして、ビット列が回転するようにずらす命令をビットローテート命令と呼びま す。オペランドのビット列だけを回転する命令と、最上位ビットと最下位ビットの間にキャリーフ ラグを挟んだビット列を回転する命令があります。 63 0 演算前 AA AAU 1 1 0 1 0 0 · · · 1 1 0 1 演算後 1 0 1 0 0 · · · 1 1 0 1 1 1bit の左ローテート 63 0 B BBN 1 B BBN 1 B BBN 0 B BBN 1 B BBN 0 B BBN 0 · · · B BBN 1 B BBN 1 B BBN 0 1 1 1 1 0 1 0 0 · · · 1 1 0 1bit の右ローテート Carry 63 0 演算前 AA AAU 0 1 1 0 1 0 0 · · · 1 1 0 1 演算後 1 1 0 1 0 0 · · · 1 1 0 1 0 キャリーを含む1bit の左ローテート Carry 63 0 A AAU 0 B BBN 1 B BBN 1 B BBN 0 B BBN 1 B BBN 0 B BBN 0 · · · B BBN 1 B BBN 1 B BBN 0 1 1 0 1 1 0 1 0 0 · · · 1 1 0 キャリーを含む1bit の右ローテート 8 整数としての値が小さくなる方向に丸められます。 9 C言語の>>演算子は、演算対象のデータが(int型のような)符号付き整数であれば算術的右シフトを、(unsigned int型のような)符号なし整数の型であれば論理的右シフトを行います。
メモ
浮動小数点演算命令 PCで使用される多くのCPUでは、整数演算やビット演算の他に、浮動小
数点数値データの四則演算を行う機械語命令が用意されています。このようなCPUでは、浮動小
数点データを記録するための専用のレジスタが数個用意されているのが普通です。たとえば、Intel
社のCore i3プロセッサなど、IA-32やIntel 64アーキテクチャのCPUでは、80 bitの浮動小数点
数値データを記憶することのできるレジスタが8個用意されており、この大きさの浮動小数点数値 データの四則演算、さらには平方根、指数関数、対数関数、三角関数の計算を行う機械語命令が用意 されています。整数演算やビット演算を組み合わせた機械語プログラムを使えば、これらの命令と 同等の計算を行うことは可能ですが、これをCPUの中でハードウェア的に実行することで、ずっ と高速に同じ計算を行うことができます。ただし、それでも、整数演算命令やビット演算命令に比 べると、浮動小数点演算命令の実行には多くのクロック数を必要とすることに注意が必要です。 メモ
3.3
アドレッシングモード
各CPUには、機械語命令のオペランドを(機械語命令の一部として)指定する方法がいくつか用意されており、これらをアドレッシングモード(addressing mode)と呼びます。どのCPUにも用
意されている基本的なアドレッシングモードとして次のようなものがあります。
即値(immediate) 扱いたいデータそのもの(定数値)を指定する方法です。ソースオペランドに のみ使われます。データのビット列そのものが機械語命令(のビット列)の一部に埋め込まれ ます。表現したいデータと同じ大きさのビット列が埋め込まれる場合もあれば、もっと短い 長さのビット列が機械語命令中に埋め込まれて、それが符号拡張10されたり、ゼロ拡張11され て使用される場合もあります。CPUによっては、即値がオペランドとなるデータ転送や演算 命令に、一般のデータ転送命令や演算命令とは別の名前が付けられていることもあります。 メモ レジスタ直接(register direct) 扱いたいデータを格納しているレジスタを指定します。ソース オペランドにもデスティネーションオペランドにも使用されます。機械語命令(のビット列) の一部には、レジスタを識別するための番号が埋め込まれます。汎用レジスタは、ソースオ ペランドにもデスティネーションオペランドにもなれるのは普通ですが、特殊な用途のレジ スタは、そのどちかになれなかったり、どちらにもなれなかったりする場合もあります。 メモ 絶対(absolute) 扱いたいデータを格納しているメモリアドレス(仮想アドレス)を指定します。 そのアドレスを表すビット列が機械語命令の一部に埋め込まれます。全体のビット列が埋め 込まれる場合もあれば、より短いビット列が埋め込まれて、それが符号拡張やゼロ拡張され て(アドレスとして)使われる場合もあります。 メモ 10元データの最上位ビット(符号付き整数表現の符号ビット)を上位の(足りない部分の)ビットすべてに補う拡張方 法で、符号付き整数の値を変えずにビット拡張ができます。 11 単に、上位の(足りない部分の)ビットを0で埋める拡張方法で、符号なし整数の値を変えずにビット拡張ができま す。
レジスタ間接(register indirect) レジスタを指定して、そのレジスタに格納されているデータを メモリアドレスとみなして、そのメモリアドレスに置かれたデータを指定します。ソースオ ペランドにもデスティネーションオペランドにも使用されます。機械語命令(のビット列)の 一部には、レジスタを識別するための番号が埋め込まれます。 レジスタ間接アドレッシングで使用されるレジスタは、通常、仮想アドレスと同じ大きさ であることが多いのですが、もし、より小さなレジスタを使用する場合は、その値が符号拡張 やゼロ拡張されて使われます。 メモ PCやスマートフォン等に使用されるCPUでは、以上4つの基本的なアドレッシングモードの他に も、以下のような、より複雑なアドレッシングモードが用意されているのが普通です。上の4つ12 と演算命令を組み合わせれば、これらのアドレッシングモードの代りをさせることは可能ですが、 その存在により、より効率的な機械語プログラムが書けるようになります。 メモ レジスタ相対(register-relative) レジスタ間接アドレッシングに似ていますが、レジスタに格納 されているデータをそのままアドレスとするのではなく、そのデータに機械語命令中に埋め 込まれた整数値を加えた結果をメモリアドレスとして使用します。加える整数値は、通常、符 号付き(正負がある)となっており、この値を変位(displacement)またはオフセット(offset) と呼びます。また、変位を加える前のアドレスをのベース(基底)アドレス(base address)と 呼び、それを指定するために用いられたレジスタをのベース(基底)レジスタ(base register) と呼びます13。これが(仮想アドレスの大きさに)符号拡張されてアドレスの計算に使用され ます。つまり、レジスタ相対アドレッシングでは、オペランドとなるデータのメモリアドレ スは ベースレジスタの値+変位 となります。 12 正確には、絶対(absolute)アドレッシングは、他の3つのアドレッシングモードとデータ転送命令を組み合わせる ことで代りをさせることができます。 13 CPUごとに、どのレジスタがベースレジスタとなれるかが決まっています。
機械語命令(のビット列)の一部には、ベースレジスタとして使用するレジスタを識別する ための番号と、変位(通常、8 bitから32 bit程度の符号付き整数表現)が埋め込まれます。 メモ プログラムカウンタ相対(PC-relative) レジスタ相対アドレッシングのベースレジスタとしてプ ログラムカウンタを使用するアドレッシングモードです。単に、相対アドレッシングと呼ぶ こともあります。データ転送命令に使われることもありますが、分岐命令等のジャンプ先の アドレスを指定する際に多用されます。 メモ インデックス修飾付きレジスタ相対 レジスタ相対アドレッシングで計算されるメモリアドレスに、 さらにもう1つのレジスタの値を加算するものです14。このレジスタをインデックスレジス
タ(index register)と呼びます。CPUによっては、単にインデックスレジスタの値を加えら れるだけではなく、その値の定数倍を加えることが許されていることもあります。インデッ クスレジスタの値に掛けられる定数はスケール値と呼ばれます15。 結局、インデックス修飾付きレジスタ間接アドレッシングでは、オペランドとなるデータ のメモリアドレスは次のように計算されることになります。 ベースレジスタの値+インデックスレジスタの値×スケール値+変位 機械語命令(のビット列)の一部には、ベースレジスタとインデックスレジスタのそれぞれを 識別するための番号と、変位、(あれば)スケール値が埋め込まれます。 C言語での配列要素へのアクセスをコンパイラが機械語プログラムに変換する際に、配列 の先頭アドレスをベースレジスタに、添字をインデックスレジスタに格納しておけば、要素 の大きさをスケール値としたインデックス修飾付きレジスタ相対アドレッシングモードを使 うと、目的の配列要素のアドレスを簡単に指定することができます16。 14ベースレジスタと変位を指定する代りに、絶対アドレスを指定して、そこにインデックスレジスタの値を加える場 合をインデックス修飾付き(絶対)アドレッシングと呼ぶこともあります。後述のスケール値が1の場合、インデックス レジスタをベースレジスタとみなせば、実質的にはレジスタ相対アドレッシングと同じものです。 15 定数倍される際に、インデックスレジスタの値自身が更新されるわけではありません。 16 配列要素が構造体のような場合は、目的の構造体メンバが構造体のどこに位置しているかを変位として指定します。
メモ メモリ間接 以上のアドレッシングモードでは、レジスタの値や機械語命令に埋め込まれた定数値 からオペランドとなるメモリアドレスを計算していますが、このようにして得られたメモリ アドレスを使ってメモリにアクセスし、そこ格納されたデータをメモリアドレスとしてオペ ランドを指定するアドレッシングをメモリ間接アドレッシングと呼びます。 たとえば、アドレスaに格納されているデータを[a]で表すことにすると、レジスタ相対 アドレッシングで指定されるメモリアドレスは、 ベースレジスタの値+変位 でしたが、これがメモリ間接アドレッシング(レジスタ相対メモリ間接アドレッシング)とな ると、指定されるアドレスは [ベースレジスタの値+変位] となります。 データ転送命令や演算命令等のオペランドをを指定するためにメモリ間接アドレッシング モードが用意されることはあまりありませんが、分岐命令のジャンプ先のアドレスを指定す るような場合に使用可能となっていることがよくあります。 原理的には、メモリ間接アドレッシングで指定されたアドレスを使って、さらに、そこに格 納されているデータをアドレスとして指定するような二重のメモリ間接アドレッシングや、 さらに多重のメモリ間接アドレッシングモードを考えることはできますが、現在主流となっ ているCPUではこのようなアドレッシングモードを使用することはできません。 メモ 自動増減分付きアドレッシング CPUによっては、レジスタ間接や(インデックス修飾付き)レジ スタ相対アドレッシングにおいて、メモリアドレスの計算の前、あるいは後に、アドレスの
計算に使用されるレジスタ(ベースレジスタ)の値を、オペランドの大きさだけ自動的に減ら したり、増やしたりする17ことができるアドレッシングモードが用意されていることもあり ます。自動増減分付きアドレッシングモードは、メモリの連続したアドレスに置かれている データに次々にアクセスしていくような場合に便利なアドレッシングモードです。通常、メ モリアドレスの計算の前に減分するモードと、メモリアドレスの計算の後に増分するモード の2種類がよく使用されます。 メモ 17 バイトアドレッシングの場合、たとえば、32 bitの大きさのデータに対するデータ転送命令や演算命令なら、アドレ ス計算に使用されるレジスタの値を4だけ減らしたり増やしたりします。
3.4
付録: Intel 64 アーキテクチャ 64 bit モードのデータ転送命令と演算命令の概要
各命令のアセンブリ言語 (情報処理実習室の Linux 環境)での書式 主要なデータ転送命令 mov α, β α の値を β へコピーする xchg α, β α と β の値を交換する lea α, β メモリオペランド α のアドレスそのものを β へ書き込む push α rspをオペランドの大きさ (バイト数) だけ減じて、そのアドレスに α をコピーする pop α アドレス rsp のデータを α にコピーし、その大きさ (バイト数) だけ rsp を増やす 主要な整数演算命令 add α, β 整数値 α、β について、β + α の計算結果を β へ書き込む sub α, β 整数値 α、β について、β− α の計算結果を β へ書き込む addc α, β 整数値 α、β について、β + α + CF の計算結果を β へ書き込む subb α, β 整数値 α、β について、β− (α + CF) の計算結果を β へ書き込む cmp α, β 整数値 α、β について、β− α の計算結果に合わせて状態フラグ群を設定する neg α 整数値 α について、−α の値を α へ書き込む inc α 整数値 α について、α + 1 の値を α へ書き込む dec α 整数値 α について、α− 1 の値を α へ書き込む 主要なビット演算命令 and α, β ビット列 α、β について、α と β のビット毎の論理積を β へ書き込む or α, β ビット列 α、β について、α と β のビット毎の論理和を β へ書き込む xor α, β ビット列 α、β について、α と β のビット毎の排他的論理和を β へ書き込む not α ビット列 α をビット毎に反転した結果を α へ書き込む shl α, β ビット列 β を α (省略すると 1) bit だけ左シフトし β へ書き込む shr α, β ビット列 β を α (省略すると 1) bit だけ論理的右シフトし β へ書き込む sar α, β ビット列 β を α (省略すると 1) bit だけ算術的右シフトし β へ書き込む rol α, β ビット列 β を α (省略すると 1) bit だけ左ローテートし β へ書き込む ror α, β ビット列 β を α (省略すると 1) bit だけ右ローテートし β へ書き込む rcl α, β ビット列 β を CF を含めて α (省略すると 1) bit だけ左ローテートし β へ書き込む rcr α, β ビット列 β を CF を含めて α (省略すると 1) bit だけ右ローテートし β へ書き込む ただし、CFはキャリーフラグのことです。各命令のオペランドの大きさ(ビット長)が自明でない場合は、movqやmovl、movw、movbのように、命令のニーモニックの末尾に q、l、w、bを付して、 オペランドの大きさが、それぞれ64 bit、32 bit、16 bit、8 bitであることを示すことができます。
レジスタの指定法 Intel 64アーキテクチャの64 bitモードでは、次の16個の64 bit汎用レジス タを使用することができます。
rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, r8, r9, r10, r11, r12, r13, r14, r15
これらのレジスタは、その一部のビット列だけを、次の表のように32 bit、16bit、8bitのレジスタ
として使用することもできます。
eax, ebx, ecx, edx, esi, edi, ebp, esp それぞれ、レジスタ rax, . . . , rsp の下位 32 bit ax, bx, cx, dx, si, di, bp, sp それぞれ、レジスタ rax, . . . , rsp の下位 16 bit al, bl, cl, dl, sil, dil, bpl, spl それぞれ、レジスタ rax, . . . , rsp の下位 8 bit
ah, bh, ch, dh それぞれ ax, . . . , dx の上位 8 bit
r8d, r9d, . . . , r15d それぞれ、レジスタ r8, r9, . . . , r15 の下位 32 bit r8w, r9w, . . . , r15w それぞれ、レジスタ r8, r9, . . . , r15 の下位 16 bit r8b, r9b, . . . , r15b それぞれ、レジスタ r8, r9, . . . , r15 の下位 8 bit
つまり、64 bitの汎用レジスタrax, rbx, rcx, rdx, rsi, rdi, rbp, rspは、その一部分を、次のよ うな名前で指定できます(raxの例)。 63 31 15 7 0 |←−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− rax−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−→| |←−−−−−−−−−−−−−−−−eax−−−−−−−−−−−−−−−→| |←−−−−−−ax−−−−−−→| |←−ah→||←−al→| また、r8, r9, . . ., r15については次のようになります(r8の例)。 63 31 15 7 0 |←−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− r8−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−→| |←−−−−−−−−−−−−−−−−r8d−−−−−−−−−−−−−−−→| |←−−−−− r8w−−−−−→| |←r8b→|
ただし、32 bit長のデータ転送命令や演算命令で、eax, ebx, ecx, edx, esi, edi, ebp, esp, r8d, r9d, . . . , r15dがデスティネーションオペランドとして指定された場合は、これらを含んでいる64 bit汎用レジスタ(rax, . . . , r15)の上位32 bitはすべて0となります。
データ転送命令や演算命令のオペランドの書式 データ転送命令や演算命令のオペランドでは、つ ぎのような書式で各種のアドレッシングモードを指定することができます18。メモリはバイトア ドレッシングで、多バイト長のデータはリトルエンディアン方式で格納されます。 $c 整数値の定数 c (即値アドレッシング) a メモリアドレス (定数) a (絶対アドレッシング) %r レジスタ r (レジスタ直接アドレッシング) d(%b) bをベースレジスタ、変位を d (省略すると 0) としたレジスタ相対アドレッシング d(%rip) 変位を d (省略すると 0) としたプログラムカウンタ相対アドレッシング d(%b, %i, s) bをベースレジスタ (省略可)、i をインデックスレジスタ、変位を d、スケール値を s (1, 2, 4, 8 のいずれか) としたインデックス修飾付きレジスタ相対アドレッシング 以下は、これらのアドレッシングモードを使用したデータ転送命令の例です。
mov $0x12345678, %rax 定数 0x0000000012345678 をレジスタ %rax に書き込む mov 0x12345678, %rbx メモリアドレス 0x12345678 に置かれたデータ (64 bit 長)
をレジスタ %rbx にコピーする
mov %rcx, 0x1c(%rbp) レジスタ %rbp の値に定数 0x1c を加えたメモリアドレス に、レジスタ %rcx の値を書き込む
mov 0x1c(%rax,%rsi,4), %edx %raxの値に、%rsi の値を 4 倍したものを加え、さらに 0x1c を加えたメモリアドレスに置かれたデータ (32 bit 長) を %edxにコピーする メモ 計算機システム II ・第 3 回・終わり 18付録冒頭の表に挙げたデータ転送命令や演算命令では、2つのオペランドαとβが、ともにメモリオペランドとな ることはありません。また、レジスタ相対アドレッシングモード(インデックス修飾付きを含む)で、ベースレジスタや インデックスレジスタとして使用できるのは64 bit長の汎用レジスタのみで、%rspはインデックスレジスタとしては 使用できません。