Top PageMASMのメモ書き TOP

x86系CPUのメモ

アドレッシング・モード

命令一覧
ニモニック OP-CODE
演算(レジスタ/メモリ ─ レジスタ間)
ADD 0000 00dw, mod reg r/m
OR 0000 10dw, mod reg r/m
ADC 0001 00dw, mod reg r/m
SBB 0001 10dw, mod reg r/m
AND 0010 00dw, mod reg r/m
SUB 0010 10dw, mod reg r/m
XOR 0011 00dw, mod reg r/m
CMP 0011 10dw, mod reg r/m
TEST 1001 010w, mod reg r/m
演算(アキュムレータ ─ 実値間)
ADD acc,imm 0000 010w
OR acc,imm 0000 110w
ADC acc,imm 0001 010w
SBB acc,imm 0001 110w
AND acc,imm 0010 010w
SUB acc,imm 0010 110w
XOR acc,imm 0011 010w
CMP acc,imm 0011 110w
演算(レジスタ/メモリ ─ 実値間)
ADD r/m,imm 1000 00dw, mod 000 r/m
OR r/m,imm 1000 00dw, mod 001 r/m
ADC r/m,imm 1000 00dw, mod 010 r/m
SBB r/m,imm 1000 00dw, mod 011 r/m
AND r/m,imm 1000 00dw, mod 100 r/m
SUB r/m,imm 1000 00dw, mod 101 r/m
XOR r/m,imm 1000 00dw, mod 110 r/m
CMP r/m,imm 1000 00dw, mod 111 r/m
inc/dec
INC reg 0100 0 reg
DEC reg 0100 1 reg
INC r/m 1111 111w, mod 001 r/m
DEC r/m 1111 111w, mod 000 r/m
ロード・ストア・転送
XCHG 1000 011w, mod reg r/m
MOV 1000 10dw, mod reg r/m
MOV (sreg) 1000 11d0, mod sreg r/m
LEA 1000 1101, mod reg r/m
XCHG eAX,reg 1001 0 reg
MOV acc,[mem] 1010 000w
MOV [mem],acc 1010 001w
MOV reg,imm 1011 w reg
MOV r/m,imm 1100 011w, mod 000 r/m
演算
TEST r/m,imm 1111 011w, mod 000 r/m
NOT r/m 1111 011w, mod 010 r/m
NEG r/m 1111 011w, mod 011 r/m
MUL r/m 1111 011w, mod 100 r/m
IMIL r/m 1111 011w, mod 101 r/m
DIV r/m 1111 011w, mod 110 r/m
IDIV r/m 1111 011w, mod 111 r/m
IMUL reg,r/m,imm0110 10w1, mod reg r/m
※d=0の時は"r/m,reg"の順、d=1の時は"reg,r/m"の順。

reg
reg w=0w=1(16bit時)w=1(32bit時)
000 AL AX EAX
001 CL CX ECX
010 DL DX EDX
011 BL BX EBX
100 AH SP ESP
101 CH BP EBP
110 DH SI ESI
111 BH DI EDI

r/m (8086モード時)
r/m mod=00 mod=01 mod=10 mod=11
000 [BX + SI] [BX + SI + imm8] [BX + SI + imm16] reg
001 [BX + DI] [BX + DI + imm8] [BX + DI + imm16] reg
010 [BP + SI] [BP + SI + imm8] [BP + SI + imm16] reg
011 [BP + DI] [BP + DI + imm8] [BP + DI + imm16] reg
100 [SI] [SI + imm8] [SI + imm16] reg
101 [DI] [DI + imm8] [DI + imm16] reg
110 [BP] [BP + imm8] [BP + imm16] reg
111 [BX] [BX + imm8] [BX + imm16] reg

r/m (IA-32モード時)
r/m mod=00 mod=01 mod=10 mod=11
000 [EAX] [EAX + imm8] [EAX + imm32] reg
001 [ECX] [ECX + imm8] [ECX + imm32] reg
010 [EDX] [EDX + imm8] [EDX + imm32] reg
011 [EBX] [EBX + imm8] [EBX + imm32] reg
100 SIB reg
101 [EIP + disp32] [EBP + imm8] [EBP + imm32] reg
110 [ESI] [ESI + imm8] [ESI + imm32] reg
111 [EDI] [EDI + imm8] [EDI + imm32] reg
※SIB時は、op-codeにSIBを追加し、 [base + index * scale + imm32] のアドレッシングモードを意味する。

SIB
basemod=00 mod=01 mod=10
000 EAX EAX + imm8 EAX + imm32
001 ECX ECX + imm8 ECX + imm32
010 EDX EDX + imm8 EDX + imm32
011 EBX EBX + imm8 EBX + imm32
100 ESP ESP + imm8 ESP + imm32
101 disp32 EBP + imm8 EBP + imm32
110 ESI ESI + imm8 ESI + imm32
111 EDI EDI + imm8 EDI + imm32

other
reg index(SIB) scale(SIB)sreg
000 EAX *1 ES
001 ECX *2 CS
010 EDX *4 SS
011 EBX *8 DS
100 FG
101 EBP GS
110 ESI
111 EDI

最適化

■V30mz (NEC)

  1. 命令はデコードが完了している。
  2. "メモリ・アクセスやI/Oアクセスにおいて、ウェイト・ステートが発生しない。"
    ウェイト・ステートが発生する場合は、ウェイト・ステートのクロック数を命令実行クロック数に加算してください。
  3. バス・ホールド要求が無い。
  4. ワード・データは、偶数アドレスに配置されている。
    奇数アドレスに配置されたワード・データをアクセスする場合は、1クロックを加算してください。
  5. 実効アドレス計算に必要なレジスタ(BX,BP,SI,DI,SP等)が、直前の命令で変更されていない。
    直前の命令で変更したレジスタを実効アドレス計算に使用する場合は、1クロックを加算してください。
    (ただし、LEA命令、ストリング命令では増加しません。)
    また、連続したPUSH,POP命令では、実行クロック数は増加しません。
    (全て1クロックで実行します。)
  6. 実効アドレス計算に必要なレジスタは1個のみである。
    実効アドレス計算に必要なレジスタが2個の場合(例: mov ax,[bx+si])、1クロックを加算してください。
  7. 分岐命令の分岐先は偶数アドレスである。
    奇数アドレスに分岐する場合は、1クロックを加算してください。

■Pentium シリーズ (intel) 共通

  1. 最新世代のコンパイラを使用し、最適化されたアプリケーションを作成する。
  2. 最適化を意識してコードを書く。
    具体的には、「グローバル変数」、「ポインタ」、「複雑な制御フロー」を避ける。
    'register’ 修飾子を使用せず、’const’ 修飾子を使用する。
    タイプ・システムを途中で変更することはせず、間接コールも行わない。
  3. 分岐予測のアルゴリズムに注意を払う。
    BTB内に履歴が存在しない分岐は、以下のように予測される。
    • 無条件分岐は分岐すると予測する。
    • 条件付き後方分岐は分岐すると予測する。
    • 条件付き前方分岐は分岐しないと予測する。
  4. パーシャル・レジスタ・ストールを避ける。(初代Pentiumは除外)
    例えば、AL,AH,AXレジスタを書き込んだ後に、EAXレジスタを読むコードを書くと、 AL,AH,AXレジスタへの書き込みがリタイアする(最低、7clock要する)。
    書き込み前に、xor eax,eax などで大きいレジスタをクリアすると、発生しない。
  5. すべてのデータのアライメントを合わせる。
    【コード】
    • ループ・エントリ・ラベルは、16バイト境界からの隔たりが16 バイト未満の時、アライメントを16 バイト境界に合わせる。
    • 条件分岐の後のラベルは、アライメントを合わせない。
    • 無条件分岐または関数コールの後のラベルは、16 バイト境界からの隔たりが8バイト未満の時、アライメントを16バイト境界に合わせる。
    【データ】
    • 8ビット・データは任意の境界にアライメントを合わせる。
    • 16ビット・データはアライメントが合った4 バイト・ワード内に収まるようにアライメントを合わせる。
    • 32ビット・データは4 バイトの整数倍の任意の境界にアライメントを合わせる。
    • 64ビット・データは8 バイトの整数倍の任意の境界にアライメントを合わせる。
    • 80ビット・データは128 ビット境界(すなわち、16 バイトの整数倍の任意の境界)にアライメントを合わせる。
  6. 命令キャッシュ・ミスを最少にし、プリフェッチを最適化するようにコードを配置する。
  7. 0x0F 以外のプリフィックス付きオペコードを避ける。
  8. 同一のメモリ領域において、大きいストアの後に小さいロードが来る事、及び、小さいストアの後に大きいロードが来ることを避ける。
    同一のメモリ領域におけるデータのロードとストアには、データ・サイズをそろえ、アドレス・アライメントを使用する。
  9. ソフトウェアによるパイプライン化を図る。
  10. 常にCALL命令とRET (return)命令をペアリングする。
  11. 自己修正型のコードを避ける。
  12. データをコード・セグメント内に入れない。
  13. できるだけ早くストア・アドレスを計算する。
  14. μOPを4 つ以上含む命令、または7Byteより長い命令を避ける。
    できれば、μopを1つしか必要としない命令を使用する。
  15. 呼び出される側のセーブ・プロシージャを呼び出す前にパーシャル(部分)レジスタをゼロにクリアする。
CPU 1stキャッシュ フェッチ Decoder ステージ
Pentium 8+8 [KByte] 4×32 [Bit]UV 5
Pentium Pro 8+8 [KByte] 4×32 [Bit]μop×3 12
MMX Pentium 16+16 [KByte] 4×32 [Bit]UV 6
Pentium II 16+16 [KByte] 4×32 [Bit]μop×3 12
Pentium III [KByte] 4×32 [Bit]μop×3

■i586 : Pentium, MMX Pentium

パイプラインのステージ
ステージ 処理内容
P 32Byteのバッファが4組あり、分岐命令が来るまで順次フェッチする。
コアは、常に4つのうち、1つのバッファからフェッチを要求し、分岐命令があったら
分岐すると予測した場合  :他のバッファに順次プリフェッチしていく。
分岐しないと予測した場合 :同じバッファでプリフェッチを続ける。
(F) MMX Pentiumのみ。
D1 デコード1
D2 ×2(UV) デコード2 実効アドレスの計算はここでする。
E ×2(UV) 実効
Wb ×2(UV) 書き込み。 それぞれに、64bitの書き込み用バッファがある。
※基本的に、命令は1ステージ1clockずつ、順次進む。
デコードの制約
  • 最初の命令がUパイプ、次の命令がVパイプに発行できる場合は、2命令を同時にデコードする。
  • Uパイプでレジスタに書き込みを行っている場合、Vパイプでそのレジスターに書き込めない。
  • Uパイプでレジスタに書き込めを行っている場合、Vパイプでそのレジスターに読み込めない。
  • 但し、フラグレジスタには適用しない。
  • 又、次の命令にも適用しない。(PUSH, POP, CALL, CMP, 条件ジャンプ)
  • 同じ4Byte境界をアクセスする場合、Vパイプの命令に1clockのペナルティーを生じる。
  • メモリアクセスにおいて、実アドレスのbit2〜4が同じときはバンクの衝突が生じ、Vパイプの命令に1clockのペナルティを生じる。
ペアリング不可能な命令(NP)
  1. CLレジスタにシフト・カウントがあるローテート・シフト命令。
  2. ロング算術演算命令。たとえば、MUL、DIV。
  3. 拡張命令。たとえば、RET、ENTER、PUSHA、MOVS、STOS、LOOPNZ。
  4. 一部の浮動小数点命令。たとえば、FSCALE、FLDCW、FST。
  5. セグメント間命令。たとえば、PUSH sreg、CALL far。
U またはV パイプに発行されるペアリング可能な命令(UV)
  1. 大部分の8/32bitの演算。(ADD, INC, XOR)
  2. すべての8/32bitの比較命令。(CMP, TEST)
  3. レジスタを使用するすべての8/32bitスタック操作。(PUSH reg, POP reg)
U パイプに発行されるペアリング可能な命令(U)

これらの命令は、U パイプに対して発行しなければならず、 Vパイプ内の適切な命令とペアリングすることができる。
これらの命令は、決してV パイプ内では実行されない。

  1. キャリーおよびボロー命令。(ADC, SBB)
  2. プリフィックス付き命令。
  3. 即値によるシフト。
  4. 一部の浮動小数点演算。(FADD, FMUL, FLD)
V パイプに発行されるペアリング可能な命令(V)

これらの命令は、U パイプでもVパイプでも実行できるが、Vパイプにあるときだけにペアリングされる。
これらの命令は、命令ポインタ(eip) を変更するので、次の命令が隣接していない場合があるため、U パイプではペアリングすることはできない。
U パイプ内の分岐は、分岐しないと予測されたときでも、次の命令とペアリングしない。

  1. 単純な制御転送命令。(CALL near, JMP near, JCC)
    これには、"JCC short"及び"JCC near"(0fプリフィックス付き)両バージョンの条件分岐命令が含まれる。
  2. fxch 命令。

■i686 : Pentium Pro, Pentium II, Pentium III

パイプラインのステージ
ステージ処理内容
BTB0
BTB1
IFU0 1次キャッシュから命令をフェッチする。
IFU1 16Byte単位でフェッチする。
IFU2 プリでコード。16Byte単位で取り出す。
ID0 デコードする。
ID1 最高3命令 (4μOPs + 1μOP + 1μOP)をデコードする。
但し、命令が複雑、若しくは命令長が7Byte以上の場合は、1clock中にデコードできる命令数が減る。
5μOP以上の命令は、デコードに数クロック要する。
 デコーダー1 : 4μOPの15Byte以内の命令をデコードできる。但し9Byte以上の場合は数クロック要。
 デコーダー2,3 : 1μOPの 8Byte以内の命令をデコードできる。
つまり、4-1-1μOPとなるように機械語をスケジューリングすると、デコードの効率は良くなる。
RAT 分岐のデコード
ROB Rb
RS 予約ステーション。リソース(実行ユニット)が利用可能になるまでμOPを保存(バッファ)する。
デコードされたμOPが順次バッファに保存され、リソース(実行ユニット)が使用可能になったら、 そのリソース(実行ユニット)で実行できるμOPを発行する。
μOPの実行順序は、動作に影響を与えない範囲で、CPUが勝手に変更する。
(平均で3clock間、予約ステーションに残るらしい。)
 実行ユニット1 : 整数・浮動小数点演算, MMX演算・乗算
 実行ユニット2 : 整数演算, MMX演算・シフト
 実行ユニット3 : ロード
 実行ユニット4 : ストア・アドレス
 実行ユニット5 : ストア・データ
最適化を考えるのであれば、これら5つのユニットをフルに活用できるように命令をスケジューリングする。
ROB Wb アーキテクチャ上の状態を順番に更新する。
μOPの実行順序は変わるが、このステージにて機械語にてコーディングされた順番で更新する。
RRF レジスタ・リタイア
※基本的に、命令は1ステージ1clockずつ順次進む。

命令 命令例 Para μOP数
レジスタへのロード・コピー MOV LEA reg, reg/mem/imm 1μOP
メモリへのストア MOV mem, reg/mem/imm 2μOP
演算(メモリアクセス無し) ADD, OR, ... reg, reg/imm 1μOP
演算(メモリからのロード有り) ADD, OR, ... reg, mem 2μOP
演算(メモリからのストア有り) ADD, OR, ... mem, reg/imm 4μOP
乗算・除算(演算結果が32,64bit)MUL IMUL DIV IDIVreg/mem 3〜4μOP
乗算(AX ← AL × reg8) MUL reg8 1μOP
乗算(レジスタ・実数のみ) IMUL reg, reg (,imm) 1μOP
乗算(メモリからのロード有り) IMUL reg, mem (, imm) 2μOP
PUSH, POP PUSH, POP reg/mem 2〜3μOP
分岐(条件分岐 含む) JMP, JZ, ... reg/imm/rel 1μOP
分岐(メモリからのロード有り) JMP, JZ, ... mem 2μOP
コール(アドレス実値の場合) CALL rel 4μOP
リターン(スタックフレーム破棄無し)RET 4μOP
※子プロセッサー(浮動小数点)関係の命令は、表中には書かなかった。(まず、自分が使わないから。)
※上以外のほとんどの命令は、5μOPを超える。つまり、コーディング時はできる限り、これらの命令を使うようにする。