intel C++ コンパイラは QuuuuuuX なコードを吐く(仮題)

マルチバイト NOP 命令のことです。

# はじめに

プログラムをしているとき，とくに意味を持たず適当な名前を付けたい場合がある。そういう時にデフォルトで用いられる名前を [メタ構文変数 - wikipedia](https://ja.wikipedia.org/wiki/メタ構文変数) と呼ぶらしい。日本では `hoge` が有名だが，英語圏では一般的に下記の順に変数名を用いるようだ。

1. `foo`
2. `bar`
3. `baz`
4. `qux`
5. `quux`

ただし，必ずしも某アニメのように6番目以降 `quuux`，`quuuux`，`quuuuux`, `quuuuuux` と続くわけでは無いようだ。

さて，突然こんな話題を上げたのは以下の理由による。

# 謎の機械語コード

さて本記事のタイトルを回収しよう。先日，自作のプログラムにおける intel C++ コンパイラの最適化ぶりをチェックするため，生成した実行ファイルの逆アセンブリを眺めていたところ，

$\color{red}{\Huge \textsf{なんじゃこりゃぁぁぁ}}$

と思ったのが下記の機械語コードである。
※該当行のみ抽出，説明の都合上アドレスを入れ替えた。

```plantuml
@startuml
<style>
root {
  margin 0
  padding 0
}
title {
  backgroundColor #202020
  roundCorner 16
  padding 0 16 16 16
  horizontalAlignment left
  fontStyle normal
  fontSize 14
  fontColor #e3e3e3
  fontName monospaced
}
</style>
sprite TITLE <svg width="640" height="32">
<path d="M0 0 v18 a6 6 0 0 0 6 6 h280 a6 6 0 0 0 6 -6 v-18" fill="#606060">
<text x="6" y="18" font-size="14" fill="white">自作プログラムの逆アセンブリ出力より抜粋</text>
</svg>
title
<$TITLE>
004058A6: <color:yellow>66</color> 2E 0F 1F 84 00 00 00  nop word ptr cs:[eax+eax+00000000h]
          00 00
									
00405C05: <color:yellow>66 66</color> 2E 0F 1F 84 00 00  nop word ptr cs:[eax+eax+00000000h]
          00 00 00

00405974: <color:yellow>66 66 66</color> 2E 0F 1F 84 00  nop word ptr cs:[eax+eax+00000000h]
          00 00 00 00

00405593: <color:yellow>66 66 66 66</color> 2E 0F 1F 84  nop word ptr cs:[eax+eax+00000000h]
          00 00 00 00 00

00405E52: <color:yellow>66 66 66 66 66</color> 2E 0F 1F  nop word ptr cs:[eax+eax+00000000h]
          84 00 00 00 00 00

00405811: <color:yellow>66 66 66 66 66 66</color> 2E 0F  nop word ptr cs:[eax+eax+00000000h]
          1F 84 00 00 00 00 00
end title
@enduml
```

命令コードの `66h` は，インテルの 80386 プロセッサ以降に追加されたオペランドサイズ・オーバーライド・プリフィクスである。デフォルトのオペランドサイズ（32bit or 16bit）に対して，プリフィクスを追加した命令に限りオペランドサイズ（32bit or 16bit）を反転させる。ただし，このプリフィクスを二つ連続して付与したからといって元に戻る訳でもないし，プリフィクスを重ねればオペランドサイズが 64bit，128bit，256bit と増えていく訳でもない。要するに一つだけで良いのだ。

# 種明かし

実をいうと，これらはマルチバイト NOP 命令と呼ばれる正規のバイト列だ。

賢明な読者はすでに気づいたかもしれないが，アドレスの下位４ビットと命令長の和が常に16になっている。実は，これらのマルチバイト NOP 命令の次のアドレスはジャンプ先になっており，本マルチバイト NOP 命令を介さず分岐命令によって飛んでくる場合の合流ポイントになっているのだ。このとき次のアドレスが16バイトの倍数になるようアラインメント調整を行うことで命令フェッチの効率を上げているのだと思われる。

以下は自作プログラムを intel C++ コンパイラでビルドして作られた実行ファイルを逆アセンブルして抽出したものだ。なお，長さ１～９バイトまでは intel のソフトウェア・デベロッパーズ・マニュアルに記載されている内容と一致している。x86 アーキテクチャにおける命令長は最大15バイト以下と決められているので，16バイト以上のマルチバイト NOP 命令は存在しない。また，これらのマルチバイト NOP 命令の大半はメモリオペランドを持つが，これらのアドレスが無効であっても例外は発生しない。

<table>
<caption>表１　マルチバイトNOP命令の例（intel C++ コンパイラの場合）</caption>
<thead>
<tr><th style="text-align:center">長さ</th>
    <th style="text-align:center">バイト列</th>
    <th style="text-align:center">アセンブリ</th></tr>
</thead>
<tbody>
<tr></tr>
<tr><td style="text-align:right">1</td>
    <td><code>90</code></td>
    <td><code>nop</code> / <code>xchg eax, eax</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">2</td>
    <td><code>66 90</code></td>
    <td><code>nop</code> / <code>xchg ax, ax</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">3</td>
    <td><code>0F 1F 00</code></td>
    <td><code>nop dword ptr [eax]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">4</td>
    <td><code>0F 1F 40 00</code></td>
    <td><code>nop dword ptr [eax+00h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">5</td>
    <td><code>0F 1F 44 00 00</code></td>
    <td><code>nop dword ptr [eax+eax*1+00h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">6</td>
    <td><code>66 0F 1F 44 00 00</code></td>
    <td><code>nop word ptr [eax+eax*1+00h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">7</td>
    <td><code>0F 1F 80 00 00 00 00</code></td>
    <td><code>nop dword ptr [eax+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">8</td>
    <td><code>0F 1F 84 00 00 00 00 00</code></td>
    <td><code>nop dword ptr [eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">9</td>
    <td><code>66 0F 1F 84 00 00 00 00</code><br><code>00</code></td>
    <td><code>nop word ptr [eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">10</td>
    <td><code>66 2E 0F 1F 84 00 00 00</code><br><code>00 00</code></td>
    <td><code>nop word ptr cs:[eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">11</td>
    <td><code>66 66 2E 0F 1F 84 00 00</code><br><code>00 00 00</code></td>
    <td><code>nop word ptr cs:[eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">12</td>
    <td><code>66 66 66 2E 0F 1F 84 00</code><br><code>00 00 00 00</code></td>
    <td><code>nop word ptr cs:[eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">13</td>
    <td><code>66 66 66 66 2E 0F 1F 84</code><br><code>00 00 00 00 00</code></td>
    <td><code>nop word ptr cs:[eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">14</td>
    <td><code>66 66 66 66 66 2E 0F 1F</code><br><code>84 00 00 00 00 00</code></td>
    <td><code>nop word ptr cs:[eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">15</td>
    <td><code>66 66 66 66 66 66 2E 0F</code><br><code>1F 84 00 00 00 00 00</code></td>
    <td><code>nop word ptr cs:[eax+eax*1+00000000h]</code></td></tr>
</tbody>
</table>

# Microsoft Visual C++ の場合

一方，Visual C++ でアセンブリ出力させると，アラインメント調整要素 `npad` の存在に気づく。`npad` はジャンプ先（ラベル）の直前に必ず挿入される訳ではなく，ループのジャンプ先のように繰り返し飛んでくる（可能性が高い）場所に挿入されるようだ。

```plantuml
@startuml
<style>
root {
  margin 0
  padding 0
}
title {
  backgroundColor #202020
  roundCorner 16
  padding 0 16 16 16
  horizontalAlignment left
  fontStyle normal
  fontSize 14
  fontColor #e3e3e3
  fontName monospaced
}
</style>
sprite TITLE <svg width="640" height="28">
<path d="M0 0 v18 a6 6 0 0 0 6 6 h294 a6 6 0 0 0 6 -6 v-18" fill="#606060">
<text x="6" y="18" font-size="14" fill="white">自作プログラムのアセンブリ出力より一部抜粋</text>
</svg>
title
<$TITLE>
        ;
        mov     ebx, DWORD PTR _e$1$[esp+28]
        mov     DWORD PTR _t$1$[esp+28], edi
        mov     edi, DWORD PTR _pivot$1$[esp+28]
        <color:yellow>npad    6</color>
<color:magenta>$LL14@sort:</color>
        push    DWORD PTR [esi+ebx*4-4]
        dec     ebx
        push    edi
        call    ebp
        add     esp, 8
        test    eax, eax
        js      SHORT <color:magenta>$LL14@sort</color>
        mov     edi, DWORD PTR _t$1$[esp+28]
        mov     DWORD PTR _e$1$[esp+28], ebx
        cmp     edi, ebx
        jge     SHORT <color:cyan>$LN142@sort</color>
        mov     ecx, DWORD PTR [esi+edi*4]
        mov     eax, DWORD PTR [esi+ebx*4]
        mov     DWORD PTR [esi+edi*4], eax
        mov     DWORD PTR [esi+ebx*4], ecx
        jmp     SHORT $LL10@sort
<color:cyan>$LN142@sort:</color>
        mov     edx, DWORD PTR _end$[esp+24]
        ;
end title
@enduml
```

この `npad` はマクロであり，Visual Studio 2022 Community Edition では下記のファイルで定義されている。

`C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\include\listing.inc`

ちなみに `npad` マクロの内容は下記のようになっている。９バイトまでは intel のソフトウェア・デベロッパーズ・マニュアルの内容と一致しており，intel C++ コンパイラと同じである。しかし10バイト以上は intel C++ コンパイラと異なり，とくに12バイト以上は２つの命令に分かれている。
ただし，筆者が確認した範囲では Visual C++ が９バイト以上のマルチバイト NOP 命令を出力した例を確認できなかった。


:::note
参考文献 [5] では11バイトのマルチバイト NOP 命令を確認しているので筆者の調査不足と思われる。
:::

<table>
<caption>表２　Microsoft Visual C++ listing.inc における <code>npad</code> マクロ</caption>
<thead>
<tr><th style="text-align:center">長さ</th>
    <th style="text-align:center">バイト列</th>
    <th style="text-align:center">アセンブリ</th></tr>
</thead>
<tbody>
<tr></tr>
<tr><td style="text-align:right">1</td>
    <td><code>90</code></td>
    <td><code>nop</code> / <code>xchg eax, eax</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">2</td>
    <td><code>66 90</code></td>
    <td><code>nop</code> / <code>xchg ax, ax</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">3</td>
    <td><code>0F 1F 00</code></td>
    <td><code>nop dword ptr [eax]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">4</td>
    <td><code>0F 1F 40 00</code></td>
    <td><code>nop dword ptr [eax+00h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">5</td>
    <td><code>0F 1F 44 00 00</code></td>
    <td><code>nop dword ptr [eax+eax*1+00h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">6</td>
    <td><code>66 0F 1F 44 00 00</code></td>
    <td><code>nop word ptr [eax+eax*1+00h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">7</td>
    <td><code>0F 1F 80 00 00 00 00</code></td>
    <td><code>nop dword ptr [eax+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">8</td>
    <td><code>0F 1F 84 00 00 00 00 00</code></td>
    <td><code>nop dword ptr [eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">9</td>
    <td><code>66 0F 1F 84 00 00 00 00 00</code></td>
    <td><code>nop word ptr [eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">10</td>
    <td><code>66 66 0F 1F 84 00 00 00 00 00</code></td>
    <td><code>nop word ptr [eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">11</td>
    <td><code>66 66 66 0F 1F 84 00 00 00 00 00</code></td>
    <td><code>nop word ptr [eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">12</td>
    <td><code>0F 1F 40 00</code><br><code>0F 1F 84 00 00 00 00 00</code></td>
    <td><code>nop dword ptr [eax+00h]</code><br><code>nop dword ptr [eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">13</td>
    <td><code>0F 1F 40 00</code><br><code>66 0F 1F 84 00 00 00 00 00</code></td>
    <td><code>nop dword ptr [eax+00h]</code><br><code>nop word ptr [eax+eax*1+00000000h]</code></td></tr>
<tr></tr>
<tr><td style="text-align:right">14</td>
    <td><code>0F 1F 40 00</code><br><code>66 66 0F 1F 84 00 00 00 00 00</code></td>
    <td><code>nop dword ptr [eax+00h]</code><br><code>nop word ptr [eax+eax*1+00000000h]</td></tr>
<tr></tr>
<tr><td style="text-align:right">15</td>
    <td><code>0F 1F 40 00</code><br><code>66 66 66 0F 1F 84 00 00 00 00 00</code></td>
    <td><code>nop dword ptr [eax+00h]</code><br><code>nop word ptr [eax+eax*1+00000000h]</code></td></tr>
</tbody>
</table>

# マルチバイト NOP 命令の注意点

## (1) レジスタストール問題

参考文献 [6] には以下の注意事項が記されている。

> 1 バイト NOP (XCHG EAX,EAX) はハードウェアによって特別にサポートされます。この NOP は 1 つのマイクロオペレーション (uop) とそれに関連するリソースを使用しますが、EAX の元の値への依存関係は解消されます。このマイクロオペレーション (uop) は、パイプラインの早い段階で実行できるため、未処理の命令の数を減らすことができ、最もコストの小さい NOP と言えます。

> その他の NOP には、ハードウェアの特別なサポートはありません。これらの NOP の入力レジスターと出力レジスターは、ハードウェアによって解釈されます。したがって、コード・ジェネレーターは、NOP ができるだけ早い時期に RS リソースをディスパッチして解放できるように、最も古い値を保持しているレジスターを入力としてコードを構成する必要があります。

すなわち，表１・２に示すマルチバイト NOP 命令は EAX レジスタを使用しているので，直前に EAX レジスタを使用している命令が存在するとレジスタストールが発生することになる。
マルチバイト NOP 命令としては別に EAX レジスタ以外を使用しても良いはずだが，筆者の調査した範囲では EAX レジスタ以外の使用例は見つからなかった。


:::note
かつて intel MPX (Memory Protection Extensions) という機能拡張があった。第6～8世代 Core プロセッサの頃に追加されたが，第10世代には引き継がれず廃止されたという黒歴史である。参考文献 [9] によると，これらの命令はマルチバイト NOP 命令の EAX レジスタ以外のエンコード領域に割り当てられたようで，廃止されたとはいえ EAX レジスタ以外は使いづらい状況である。
:::

## (2) プリフィクス使い過ぎ問題

また，参考文献 [7] の「旧世代の Intel Atom マイクロアーキテクチャーとソフトウェアの最適化」を見ると次のような記述がある。

> 複数のプリフィクスを持つ命令は、デコーダーのスループットを制限します。プリフィクスとエスケープの合計バイト数が制限に当てはまります。命令のプリフィクス + エスケープは、以下のマイクロアーキテクチャーの制限を超えないようにします。
> - Silvermont マイクロアーキテクチャー: 3 バイトを超えるとペナルティーが発生します。
> - Goldmont マイクロアーキテクチャー以降: 4 バイトを超えるとペナルティーが発生します。したがって、上位 8 つのレジスターをアクセスするインテル SSE4 や AES 命令には、ペナルティーが科せられません。
> - Silvermont と Goldmont マイクロアーキテクチャーでは、デコーダー 0 のみがプリフィクス/エスケープ・バイトの制限を超えた命令をデコードできます。

ちなみに `66h` はオペランドサイズ・オーバーライド・プリフィクス，`2Eh` はセグメント・オーバーライド・プリフィクス，`0Fh` はエスケープコードであるから，表１の長さ１５バイトのマルチバイト NOP 命令はプリフィクスとエスケープコードだけで８バイトを消費していることになり，旧世代のプロセッサではペナルティが大きいと思われる。

# マルチバイト NOP 命令の効果

プリフィクスを６個も７個も付けてしまうとパフォーマンスの低下が気になるので検証することにした。

１～１５バイトまでのマルチバイト NOP 命令を 1800 bytes 分並べ，それを 400,000,000 回繰り返して実行時間を計測する。コア部分はアセンブラで記述し，C言語から呼び出すようにした。

計測環境を以下に示す。

- intel Core i-7 12700 プロセッサ 2.1GHz（最大 4.9GHz）, 32GB
- Windows10 22H2
- Visual Studio 2022 Community Edition
  32bit 版 C++ コンパイラ及びアセンブラを使用

:::note
なぜ 1800 bytes かというと，Golden Cove の uOPs キャッシュ（4Kエントリ）に収まるようにしたからである。
:::

計測結果を以下に示す。総実行時間 $t$ とおくと，1800 bytes 分の実行時間 $t_1 = t / 400000000$ であり，最大動作周波数 $\phi$ とおくと，１サイクルあたりの並列実行数 $p$ は次の式で表される。


```math
p = \frac{\displaystyle\frac{1800}{n}}{t_1 \times \phi}
```


<table>
<caption>表３　マルチバイト NOP 命令<br>1800 bytes 分の実行時間（ns）</caption>
<thead>
<tr><th style="text-align:center">長さ</th>
    <th style="text-align:center">intel C++<br>Compiler</th>
    <th style="text-align:center">Microsoft<br>Visual C++</th></tr>
</thead>
<tbody>
<tr><td style="text-align:right">1</td>
    <td style="text-align:right">65.248</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">2</td>
    <td style="text-align:right">31.660</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">3</td>
    <td style="text-align:right">23.290</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">4</td>
    <td style="text-align:right">15.558</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">5</td>
    <td style="text-align:right">12.515</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">6</td>
    <td style="text-align:right">10.365</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">7</td>
    <td style="text-align:right">8.863</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">8</td>
    <td style="text-align:right">7.773</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">9</td>
    <td style="text-align:right">6.920</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">10</td>
    <td style="text-align:right">6.273</td>
    <td style="text-align:right">6.240</td></tr>
<tr><td style="text-align:right">11</td>
    <td style="text-align:right">5.693</td>
    <td style="text-align:right">5.690</td></tr>
<tr><td style="text-align:right">12</td>
    <td style="text-align:right">5.223</td>
    <td style="text-align:right">10.350</td></tr>
<tr><td style="text-align:right">13</td>
    <td style="text-align:right">4.828</td>
    <td style="text-align:right">9.535</td></tr>
<tr><td style="text-align:right">14</td>
    <td style="text-align:right">4.540</td>
    <td style="text-align:right">8.918</td></tr>
<tr><td style="text-align:right">15</td>
    <td style="text-align:right">4.345</td>
    <td style="text-align:right">8.283</td></tr>
</tbody>
</table>

<table>
<caption>表４　マルチバイト NOP 命令<br>１サイクルあたりの実行数（個）</caption>
<thead>
<tr><th style="text-align:center">長さ</th>
    <th style="text-align:center">intel C++<br>Compiler</th>
    <th style="text-align:center">Microsoft<br>Visual C++</th></tr>
</thead>
<tbody>
<tr><td style="text-align:right">1</td>
    <td style="text-align:right">5.630</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">2</td>
    <td style="text-align:right">5.801</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">3</td>
    <td style="text-align:right">5.258</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">4</td>
    <td style="text-align:right">5.903</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">5</td>
    <td style="text-align:right">5.871</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">6</td>
    <td style="text-align:right">5.907</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">7</td>
    <td style="text-align:right">5.921</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">8</td>
    <td style="text-align:right">5.908</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">9</td>
    <td style="text-align:right">5.898</td>
    <td style="text-align:center">同左</td></tr>
<tr><td style="text-align:right">10</td>
    <td style="text-align:right">5.856</td>
    <td style="text-align:right">5.887</td></tr>
<tr><td style="text-align:right">11</td>
    <td style="text-align:right">5.867</td>
    <td style="text-align:right">5.869</td></tr>
<tr><td style="text-align:right">12</td>
    <td style="text-align:right">5.862</td>
    <td style="text-align:right">2.958</td></tr>
<tr><td style="text-align:right">13</td>
    <td style="text-align:right">5.853</td>
    <td style="text-align:right">2.964</td></tr>
<tr><td style="text-align:right">14</td>
    <td style="text-align:right">5.780</td>
    <td style="text-align:right">2.942</td></tr>
<tr><td style="text-align:right">15</td>
    <td style="text-align:right">5.636</td>
    <td style="text-align:right">2.957</td></tr>
</tbody>
</table>

こういうのはグラフにすると一目瞭然である。intel C++ コンパイラの吐くマルチバイト NOP 命令のほうは綺麗な反比例になっている。すなわち命令長は長くとも１バイトの NOP 命令と同じ時間で実行できているのだ。一方，Microsoft Visual C++ コンパイラの出力を見てみると，11バイト以下は１命令なのでintel C++ コンパイラと同じだが，12バイト以上では２命令に分割してしまうのでちょうど２倍の時間を要している。

<font color="#5B9BD5">◆</font>intel C++ Compiler, <font color="#ED7D31">◆</font>Microsoft Visual C++

```plantuml
@startuml
<style>
root {
  padding 0
  margin 0
}
title {
  fontStyle normal
  fontSize 16
}
</style>
sprite FIGURE <svg width="700" height="440">
<g fill="lightgray">
<path d="M40 30 h640 v1 h-640">
<path d="M40 80 h640 v1 h-640">
<path d="M40 130 h640 v1 h-640">
<path d="M40 180 h640 v1 h-640">
<path d="M40 230 h640 v1 h-640">
<path d="M40 280 h640 v1 h-640">
<path d="M40 330 h640 v1 h-640">
<path d="M40 380 h640 v1 h-640">
<path d="M40 30 v350 h1 v-350">
<path d="M120 30 v350 h1 v-350">
<path d="M200 30 v350 h1 v-350">
<path d="M280 30 v350 h1 v-350">
<path d="M360 30 v350 h1 v-350">
<path d="M440 30 v350 h1 v-350">
<path d="M520 30 v350 h1 v-350">
<path d="M600 30 v350 h1 v-350">
<path d="M680 30 v350 h1 v-350">
</g>
<text x="40" y="20" font-size="16" fill="black">[ns]</text>
<text x="15" y="36" font-size="16" fill="black">70</text>
<text x="15" y="86" font-size="16" fill="black">60</text>
<text x="15" y="136" font-size="16" fill="black">50</text>
<text x="15" y="186" font-size="16" fill="black">40</text>
<text x="15" y="236" font-size="16" fill="black">30</text>
<text x="15" y="286" font-size="16" fill="black">20</text>
<text x="15" y="336" font-size="16" fill="black">10</text>
<text x="25" y="386" font-size="16" fill="black">0</text>
<text x="36" y="400" font-size="16" fill="black">0</text>
<text x="116" y="400" font-size="16" fill="black">2</text>
<text x="196" y="400" font-size="16" fill="black">4</text>
<text x="276" y="400" font-size="16" fill="black">6</text>
<text x="356" y="400" font-size="16" fill="black">8</text>
<text x="430" y="400" font-size="16" fill="black">10</text>
<text x="510" y="400" font-size="16" fill="black">12</text>
<text x="590" y="400" font-size="16" fill="black">14</text>
<text x="670" y="400" font-size="16" fill="black">16</text>
<text x="310" y="420" font-size="16" fill="black">長さ[bytes]</text>
<g fill="#5B9BD5">
<path d="M80 52.8 h172.6 v2 h-172.6" transform="rotate(76.6,80,53.8)">
<path d="M120 220.7 h57.9 v2 h-57.9" transform="rotate(46.3,120,221.7)">
<path d="M160 262.6 h55.6 v2 h-55.6" transform="rotate(44,160,263.6)">
<path d="M200 301.2 h42.8 v2 h-42.8" transform="rotate(20.8,200,302.2)">
<path d="M240 316.4 h41.4 v2 h-41.4" transform="rotate(15,240,317.4)">
<path d="M280 327.2 h40.7 v2 h-40.7" transform="rotate(10.6,280,328.2)">
<path d="M320 334.7 h40.4 v2 h-40.4" transform="rotate(7.8,320,335.7)">
<path d="M360 340.1 h40.2 v2 h-40.2" transform="rotate(6.1,360,341.1)">
<path d="M400 344.4 h40.1 v2 h-40.1" transform="rotate(4.6,400,345.4)">
<path d="M440 347.6 h40.1 v2 h-40.1" transform="rotate(4.1,440,348.6)">
<path d="M480 350.5 h40.1 v2 h-40.1" transform="rotate(3.4,480,351.5)">
<path d="M520 352.9 h40 v2 h-40" transform="rotate(2.8,520,353.9)">
<path d="M560 354.9 h40 v2 h-40" transform="rotate(2.1,560,355.9)">
<path d="M600 356.3 h40 v2 h-40" transform="rotate(1.4,600,357.3)">
<path d="M80 47.8 l-6 6 l6 6 l6 -6">
<path d="M120 215.7 l-6 6 l6 6 l6 -6">
<path d="M160 257.6 l-6 6 l6 6 l6 -6">
<path d="M200 296.2 l-6 6 l6 6 l6 -6">
<path d="M240 311.4 l-6 6 l6 6 l6 -6">
<path d="M280 322.2 l-6 6 l6 6 l6 -6">
<path d="M320 329.7 l-6 6 l6 6 l6 -6">
<path d="M360 335.1 l-6 6 l6 6 l6 -6">
<path d="M400 339.4 l-6 6 l6 6 l6 -6">
<path d="M440 342.6 l-6 6 l6 6 l6 -6">
<path d="M480 345.5 l-6 6 l6 6 l6 -6">
<path d="M520 347.9 l-6 6 l6 6 l6 -6">
<path d="M560 349.9 l-6 6 l6 6 l6 -6">
<path d="M600 351.3 l-6 6 l6 6 l6 -6">
<path d="M640 352.3 l-6 6 l6 6 l6 -6">
</g>
<g fill="#ED7D31">
<path d="M440 347.8 h40.1 v2 h-40.1" transform="rotate(3.9,440,348.8)">
<path d="M480 350.6 h46.3 v2 h-46.3" transform="rotate(-30.2,480,351.6)">
<path d="M520 327.3 h40.2 v2 h-40.2" transform="rotate(5.8,520,328.3)">
<path d="M560 331.3 h40.1 v2 h-40.1" transform="rotate(4.4,560,332.3)">
<path d="M600 334.4 h40.1 v2 h-40.1" transform="rotate(4.5,600,335.4)">
<path d="M440 342.8 l-6 6 l6 6 l6 -6">
<path d="M480 345.6 l-6 6 l6 6 l6 -6">
<path d="M520 322.3 l-6 6 l6 6 l6 -6">
<path d="M560 326.3 l-6 6 l6 6 l6 -6">
<path d="M600 329.4 l-6 6 l6 6 l6 -6">
<path d="M640 332.6 l-6 6 l6 6 l6 -6">
</g>
</svg>
title
<$FIGURE>
図１　マルチバイト NOP 命令 1800 bytes 分の実行時間
end title
@enduml
```

１サイクルあたりの並列実行数を求めてみると，ほぼ６命令を並列実行できているように思える。

```plantuml
@startuml
<style>
root {
  padding 0
  margin 0
}
title {
  fontStyle normal
  fontSize 16
}
</style>
sprite FIGURE <svg width="700" height="440">
<g fill="lightgray">
<path d="M40 30 h640 v1 h-640">
<path d="M40 80 h640 v1 h-640">
<path d="M40 130 h640 v1 h-640">
<path d="M40 180 h640 v1 h-640">
<path d="M40 230 h640 v1 h-640">
<path d="M40 280 h640 v1 h-640">
<path d="M40 330 h640 v1 h-640">
<path d="M40 380 h640 v1 h-640">
<path d="M40 30 v350 h1 v-350">
<path d="M120 30 v350 h1 v-350">
<path d="M200 30 v350 h1 v-350">
<path d="M280 30 v350 h1 v-350">
<path d="M360 30 v350 h1 v-350">
<path d="M440 30 v350 h1 v-350">
<path d="M520 30 v350 h1 v-350">
<path d="M600 30 v350 h1 v-350">
<path d="M680 30 v350 h1 v-350">
</g>
<text x="40" y="20" font-size="16" fill="black">[個]</text>
<text x="25" y="36" font-size="16" fill="black">7</text>
<text x="25" y="86" font-size="16" fill="black">6</text>
<text x="25" y="136" font-size="16" fill="black">5</text>
<text x="25" y="186" font-size="16" fill="black">4</text>
<text x="25" y="236" font-size="16" fill="black">3</text>
<text x="25" y="286" font-size="16" fill="black">2</text>
<text x="25" y="336" font-size="16" fill="black">1</text>
<text x="25" y="386" font-size="16" fill="black">0</text>
<text x="36" y="400" font-size="16" fill="black">0</text>
<text x="116" y="400" font-size="16" fill="black">2</text>
<text x="196" y="400" font-size="16" fill="black">4</text>
<text x="276" y="400" font-size="16" fill="black">6</text>
<text x="356" y="400" font-size="16" fill="black">8</text>
<text x="430" y="400" font-size="16" fill="black">10</text>
<text x="510" y="400" font-size="16" fill="black">12</text>
<text x="590" y="400" font-size="16" fill="black">14</text>
<text x="670" y="400" font-size="16" fill="black">16</text>
<text x="310" y="420" font-size="16" fill="black">長さ[bytes]</text>
<g fill="#5B9BD5">
<path d="M80 97.5 h40.9 v2 h-40.9" transform="rotate(-12.1,80,98.5)">
<path d="M120 88.9 h48.4 v2 h-48.4" transform="rotate(34.2,120,89.9)">
<path d="M160 116.1 h51.4 v2 h-51.4" transform="rotate(-38.9,160,117.1)">
<path d="M200 83.8 h40 v2 h-40" transform="rotate(2.3,200,84.8)">
<path d="M240 85.5 h40 v2 h-40" transform="rotate(-2.6,240,86.5)">
<path d="M280 83.7 h40 v2 h-40" transform="rotate(-1,280,84.7)">
<path d="M320 82.9 h40 v2 h-40" transform="rotate(1,320,83.9)">
<path d="M360 83.6 h40 v2 h-40" transform="rotate(0.7,360,84.6)">
<path d="M400 84.1 h40.1 v2 h-40.1" transform="rotate(3,400,85.1)">
<path d="M440 86.2 h40 v2 h-40" transform="rotate(-0.7,440,87.2)">
<path d="M480 85.7 h40 v2 h-40" transform="rotate(0.4,480,86.7)">
<path d="M520 85.9 h40 v2 h-40" transform="rotate(0.6,520,86.9)">
<path d="M560 86.3 h40.2 v2 h-40.2" transform="rotate(5.3,560,87.3)">
<path d="M600 90 h40.6 v2 h-40.6" transform="rotate(10.1,600,91)">
<path d="M80 92.5 l-6 6 l6 6 l6 -6">
<path d="M120 83.9 l-6 6 l6 6 l6 -6">
<path d="M160 111.1 l-6 6 l6 6 l6 -6">
<path d="M200 78.8 l-6 6 l6 6 l6 -6">
<path d="M240 80.5 l-6 6 l6 6 l6 -6">
<path d="M280 78.7 l-6 6 l6 6 l6 -6">
<path d="M320 77.9 l-6 6 l6 6 l6 -6">
<path d="M360 78.6 l-6 6 l6 6 l6 -6">
<path d="M400 79.1 l-6 6 l6 6 l6 -6">
<path d="M440 81.2 l-6 6 l6 6 l6 -6">
<path d="M480 80.7 l-6 6 l6 6 l6 -6">
<path d="M520 80.9 l-6 6 l6 6 l6 -6">
<path d="M560 81.3 l-6 6 l6 6 l6 -6">
<path d="M600 85 l-6 6 l6 6 l6 -6">
<path d="M640 92.2 l-6 6 l6 6 l6 -6">
</g>
<g fill="#ED7D31">
<path d="M440 84.7 h40 v2 h-40" transform="rotate(1.3,440,85.7)">
<path d="M480 85.5 h151 v2 h-151" transform="rotate(74.6,480,86.5)">
<path d="M520 231.1 h40 v2 h-40" transform="rotate(-0.4,520,232.1)">
<path d="M560 230.8 h40 v2 h-40" transform="rotate(1.5,560,231.8)">
<path d="M600 231.9 h40 v2 h-40" transform="rotate(-1,600,232.9)">
<path d="M440 79.7 l-6 6 l6 6 l6 -6">
<path d="M480 80.5 l-6 6 l6 6 l6 -6">
<path d="M520 226.1 l-6 6 l6 6 l6 -6">
<path d="M560 225.8 l-6 6 l6 6 l6 -6">
<path d="M600 226.9 l-6 6 l6 6 l6 -6">
<path d="M640 226.2 l-6 6 l6 6 l6 -6">
</g>
</svg>
title
<$FIGURE>
図２　マルチバイト NOP 命令１サイクルあたりの実行数
end title
@enduml
```

:::note
参考文献 [8] によると Golden Cove のアウト・オブ・オーダーエンジンは最大６命令を発行可能である。実行ユニットである ALU や LEA は５個しかないが，たぶんそれらを使わないので済むので６命令を並列実行できていると思われる。
:::

# 旧世代 Core プロセッサの場合

下記の環境でも調べてみた。

- intel Core i5-10400 プロセッサ 2.9GHz（最大 4.3GHz）, 16GB
- Windows 10 22H2

Core i7-12700 プロセッサの結果と比較してみよう。

<table>
<caption>表５　マルチバイト NOP 命令<br>1800 bytes 分の実行時間（ns）</caption>
<thead>
<tr><th style="text-align:center">コンパイラ</th>
    <th style="text-align:center">長<br>さ</th>
    <th style="text-align:center">i7-<br>12700</th>
    <th style="text-align:center">i5-<br>10400</th></tr>
</thead>
<tbody>
<tr><th rowspan=15>intel<br>C++<br>Compiler</th>
    <td style="text-align:right">1</td>
    <td style="text-align:right">65.248</td>
    <td style="text-align:right">107.230</td></tr>
<tr><td style="text-align:right">2</td>
    <td style="text-align:right">31.660</td>
    <td style="text-align:right">53.940</td></tr>
<tr><td style="text-align:right">3</td>
    <td style="text-align:right">23.290</td>
    <td style="text-align:right">36.003</td></tr>
<tr><td style="text-align:right">4</td>
    <td style="text-align:right">15.558</td>
    <td style="text-align:right">27.003</td></tr>
<tr><td style="text-align:right">5</td>
    <td style="text-align:right">12.515</td>
    <td style="text-align:right">21.598</td></tr>
<tr><td style="text-align:right">6</td>
    <td style="text-align:right">10.365</td>
    <td style="text-align:right">17.740</td></tr>
<tr><td style="text-align:right">7</td>
    <td style="text-align:right">8.863</td>
    <td style="text-align:right">15.433</td></tr>
<tr><td style="text-align:right">8</td>
    <td style="text-align:right">7.773</td>
    <td style="text-align:right">13.533</td></tr>
<tr><td style="text-align:right">9</td>
    <td style="text-align:right">6.920</td>
    <td style="text-align:right">13.423</td></tr>
<tr><td style="text-align:right">10</td>
    <td style="text-align:right">6.273</td>
    <td style="text-align:right">13.413</td></tr>
<tr><td style="text-align:right">11</td>
    <td style="text-align:right">5.693</td>
    <td style="text-align:right">12.190</td></tr>
<tr><td style="text-align:right">12</td>
    <td style="text-align:right">5.223</td>
    <td style="text-align:right">9.078</td></tr>
<tr><td style="text-align:right">13</td>
    <td style="text-align:right">4.828</td>
    <td style="text-align:right">8.313</td></tr>
<tr><td style="text-align:right">14</td>
    <td style="text-align:right">4.540</td>
    <td style="text-align:right">7.788</td></tr>
<tr><td style="text-align:right">15</td>
    <td style="text-align:right">4.345</td>
    <td style="text-align:right">7.228</td></tr>
<tr><th rowspan=6>Microsoft<br>Visual+<br>C++</th>
    <td style="text-align:right">10</td>
    <td style="text-align:right">6.240</td>
    <td style="text-align:right">13.410</td></tr>
<tr><td style="text-align:right">11</td>
    <td style="text-align:right">5.690</td>
    <td style="text-align:right">12.190</td></tr>
<tr><td style="text-align:right">12</td>
    <td style="text-align:right">10.350</td>
    <td style="text-align:right">17.913</td></tr>
<tr><td style="text-align:right">13</td>
    <td style="text-align:right">9.535</td>
    <td style="text-align:right">16.560</td></tr>
<tr><td style="text-align:right">14</td>
    <td style="text-align:right">8.918</td>
    <td style="text-align:right">15.505</td></tr>
<tr><td style="text-align:right">15</td>
    <td style="text-align:right">8.283</td>
    <td style="text-align:right">14.443</td></tr>
</tbody>
</table>

<table>
<caption>表６　マルチバイト NOP 命令<br>１サイクルあたりの実行数（個）</caption>
<thead>
<tr><th style="text-align:center">コンパイラ</th>
    <th style="text-align:center">長<br>さ</th>
    <th style="text-align:center">i7-<br>12700</th>
    <th style="text-align:center">i5-<br>10400</th></tr>
</thead>
<tbody>
<tr><th rowspan=15>intel<br>C++<br>Compiler</th>
    <td style="text-align:right">1</td>
    <td style="text-align:right">5.630</td>
    <td style="text-align:right">3.904</td></tr>
<tr><td style="text-align:right">2</td>
    <td style="text-align:right">5.801</td>
    <td style="text-align:right">3.880</td></tr>
<tr><td style="text-align:right">3</td>
    <td style="text-align:right">5.258</td>
    <td style="text-align:right">3.876</td></tr>
<tr><td style="text-align:right">4</td>
    <td style="text-align:right">5.903</td>
    <td style="text-align:right">3.876</td></tr>
<tr><td style="text-align:right">5</td>
    <td style="text-align:right">5.871</td>
    <td style="text-align:right">3.876</td></tr>
<tr><td style="text-align:right">6</td>
    <td style="text-align:right">5.907</td>
    <td style="text-align:right">3.933</td></tr>
<tr><td style="text-align:right">7</td>
    <td style="text-align:right">5.921</td>
    <td style="text-align:right">3.875</td></tr>
<tr><td style="text-align:right">8</td>
    <td style="text-align:right">5.908</td>
    <td style="text-align:right">3.867</td></tr>
<tr><td style="text-align:right">9</td>
    <td style="text-align:right">5.898</td>
    <td style="text-align:right">3.465</td></tr>
<tr><td style="text-align:right">10</td>
    <td style="text-align:right">5.856</td>
    <td style="text-align:right">3.121</td></tr>
<tr><td style="text-align:right">11</td>
    <td style="text-align:right">5.867</td>
    <td style="text-align:right">3.122</td></tr>
<tr><td style="text-align:right">12</td>
    <td style="text-align:right">5.862</td>
    <td style="text-align:right">3.843</td></tr>
<tr><td style="text-align:right">13</td>
    <td style="text-align:right">5.853</td>
    <td style="text-align:right">3.874</td></tr>
<tr><td style="text-align:right">14</td>
    <td style="text-align:right">5.780</td>
    <td style="text-align:right">3.840</td></tr>
<tr><td style="text-align:right">15</td>
    <td style="text-align:right">5.636</td>
    <td style="text-align:right">3.861</td></tr>
<tr><th rowspan=6>Microsoft<br>Visual+<br>C++</th>
    <td style="text-align:right">10</td>
    <td style="text-align:right">5.887</td>
    <td style="text-align:right">3.122</td></tr>
<tr><td style="text-align:right">11</td>
    <td style="text-align:right">5.869</td>
    <td style="text-align:right">3.122</td></tr>
<tr><td style="text-align:right">12</td>
    <td style="text-align:right">2.958</td>
    <td style="text-align:right">1.947</td></tr>
<tr><td style="text-align:right">13</td>
    <td style="text-align:right">2.964</td>
    <td style="text-align:right">1.944</td></tr>
<tr><td style="text-align:right">14</td>
    <td style="text-align:right">2.942</td>
    <td style="text-align:right">1.928</td></tr>
<tr><td style="text-align:right">15</td>
    <td style="text-align:right">2.957</td>
    <td style="text-align:right">1.932</td></tr>
</tbody>
</table>

こういうのはグラフにすると分かり易い。第10世代Coreプロセッサの場合，最大命令発行数は４個っぽい。ただし長さ10～11バイトにかけて並列度が約３個に落ちてしまうのが謎である。長すぎるプリフィクスに対するペナルティであるならば，12バイト以上で並列度が４個に戻らないからだ。

<font color="#5B9BD5">◆</font> Core i7-12700 intel C++ Compiler，<font color="#ED7D31">◆</font> Core i7-12700 Microsoft Visual C++
<font color=#A5A5A5>◆</font> Core i5-10400 intel C++ Compiler，<font color=#FFC000>◆</font> Core i5-10400 Microsoft Visual C++

```plantuml
@startuml
<style>
root {
  padding 0
  margin 0
}
title {
  fontStyle normal
  fontSize 16
}
</style>
sprite FIGURE <svg width="700" height="440">
<g fill="lightgray">
<path d="M40 30 h640 v1 h-640">
<path d="M40 80 h640 v1 h-640">
<path d="M40 130 h640 v1 h-640">
<path d="M40 180 h640 v1 h-640">
<path d="M40 230 h640 v1 h-640">
<path d="M40 280 h640 v1 h-640">
<path d="M40 330 h640 v1 h-640">
<path d="M40 380 h640 v1 h-640">
<path d="M40 30 v350 h1 v-350">
<path d="M120 30 v350 h1 v-350">
<path d="M200 30 v350 h1 v-350">
<path d="M280 30 v350 h1 v-350">
<path d="M360 30 v350 h1 v-350">
<path d="M440 30 v350 h1 v-350">
<path d="M520 30 v350 h1 v-350">
<path d="M600 30 v350 h1 v-350">
<path d="M680 30 v350 h1 v-350">
</g>
<text x="40" y="20" font-size="16" fill="black">[個]</text>
<text x="25" y="36" font-size="16" fill="black">7</text>
<text x="25" y="86" font-size="16" fill="black">6</text>
<text x="25" y="136" font-size="16" fill="black">5</text>
<text x="25" y="186" font-size="16" fill="black">4</text>
<text x="25" y="236" font-size="16" fill="black">3</text>
<text x="25" y="286" font-size="16" fill="black">2</text>
<text x="25" y="336" font-size="16" fill="black">1</text>
<text x="25" y="386" font-size="16" fill="black">0</text>
<text x="36" y="400" font-size="16" fill="black">0</text>
<text x="116" y="400" font-size="16" fill="black">2</text>
<text x="196" y="400" font-size="16" fill="black">4</text>
<text x="276" y="400" font-size="16" fill="black">6</text>
<text x="356" y="400" font-size="16" fill="black">8</text>
<text x="430" y="400" font-size="16" fill="black">10</text>
<text x="510" y="400" font-size="16" fill="black">12</text>
<text x="590" y="400" font-size="16" fill="black">14</text>
<text x="670" y="400" font-size="16" fill="black">16</text>
<text x="310" y="420" font-size="16" fill="black">長さ[bytes]</text>
<g fill="#5B9BD5">
<path d="M80 97.5 h40.9 v2 h-40.9" transform="rotate(-12.1,80,98.5)">
<path d="M120 88.9 h48.4 v2 h-48.4" transform="rotate(34.2,120,89.9)">
<path d="M160 116.1 h51.4 v2 h-51.4" transform="rotate(-38.9,160,117.1)">
<path d="M200 83.8 h40 v2 h-40" transform="rotate(2.3,200,84.8)">
<path d="M240 85.5 h40 v2 h-40" transform="rotate(-2.6,240,86.5)">
<path d="M280 83.7 h40 v2 h-40" transform="rotate(-1,280,84.7)">
<path d="M320 82.9 h40 v2 h-40" transform="rotate(1,320,83.9)">
<path d="M360 83.6 h40 v2 h-40" transform="rotate(0.7,360,84.6)">
<path d="M400 84.1 h40.1 v2 h-40.1" transform="rotate(3,400,85.1)">
<path d="M440 86.2 h40 v2 h-40" transform="rotate(-0.7,440,87.2)">
<path d="M480 85.7 h40 v2 h-40" transform="rotate(0.4,480,86.7)">
<path d="M520 85.9 h40 v2 h-40" transform="rotate(0.6,520,86.9)">
<path d="M560 86.3 h40.2 v2 h-40.2" transform="rotate(5.3,560,87.3)">
<path d="M600 90 h40.6 v2 h-40.6" transform="rotate(10.1,600,91)">
<path d="M80 92.5 l-6 6 l6 6 l6 -6">
<path d="M120 83.9 l-6 6 l6 6 l6 -6">
<path d="M160 111.1 l-6 6 l6 6 l6 -6">
<path d="M200 78.8 l-6 6 l6 6 l6 -6">
<path d="M240 80.5 l-6 6 l6 6 l6 -6">
<path d="M280 78.7 l-6 6 l6 6 l6 -6">
<path d="M320 77.9 l-6 6 l6 6 l6 -6">
<path d="M360 78.6 l-6 6 l6 6 l6 -6">
<path d="M400 79.1 l-6 6 l6 6 l6 -6">
<path d="M440 81.2 l-6 6 l6 6 l6 -6">
<path d="M480 80.7 l-6 6 l6 6 l6 -6">
<path d="M520 80.9 l-6 6 l6 6 l6 -6">
<path d="M560 81.3 l-6 6 l6 6 l6 -6">
<path d="M600 85 l-6 6 l6 6 l6 -6">
<path d="M640 92.2 l-6 6 l6 6 l6 -6">
</g>
<g fill="#ED7D31">
<path d="M440 84.7 h40 v2 h-40" transform="rotate(1.3,440,85.7)">
<path d="M480 85.5 h151 v2 h-151" transform="rotate(74.6,480,86.5)">
<path d="M520 231.1 h40 v2 h-40" transform="rotate(-0.4,520,232.1)">
<path d="M560 230.8 h40 v2 h-40" transform="rotate(1.5,560,231.8)">
<path d="M600 231.9 h40 v2 h-40" transform="rotate(-1,600,232.9)">
<path d="M440 79.7 l-6 6 l6 6 l6 -6">
<path d="M480 80.5 l-6 6 l6 6 l6 -6">
<path d="M520 226.1 l-6 6 l6 6 l6 -6">
<path d="M560 225.8 l-6 6 l6 6 l6 -6">
<path d="M600 226.9 l-6 6 l6 6 l6 -6">
<path d="M640 226.2 l-6 6 l6 6 l6 -6">
</g>
<g fill="#A5A5A5">
<path d="M80 183.8 h40 v2 h-40" transform="rotate(1.7,80,184.8)">
<path d="M120 185 h40 v2 h-40" transform="rotate(0.3,120,186)">
<path d="M160 185.2 h40 v2 h-40" transform="rotate(0,160,186.2)">
<path d="M200 185.2 h40 v2 h-40" transform="rotate(-0.1,200,186.2)">
<path d="M240 185.2 h40.1 v2 h-40.1" transform="rotate(-4,240,186.2)">
<path d="M280 182.4 h40.1 v2 h-40.1" transform="rotate(4.1,280,183.4)">
<path d="M320 185.3 h40 v2 h-40" transform="rotate(0.6,320,186.3)">
<path d="M360 185.7 h44.8 v2 h-44.8" transform="rotate(26.6,360,186.7)">
<path d="M400 205.7 h43.5 v2 h-43.5" transform="rotate(23.3,400,206.7)">
<path d="M440 222.9 h40 v2 h-40" transform="rotate(-0.1,440,223.9)">
<path d="M480 222.9 h53.8 v2 h-53.8" transform="rotate(-42,480,223.9)">
<path d="M520 186.9 h40 v2 h-40" transform="rotate(-2.2,520,187.9)">
<path d="M560 185.3 h40 v2 h-40" transform="rotate(2.4,560,186.3)">
<path d="M600 187 h40 v2 h-40" transform="rotate(-1.6,600,188)">
<path d="M80 178.8 l-6 6 l6 6 l6 -6">
<path d="M120 180 l-6 6 l6 6 l6 -6">
<path d="M160 180.2 l-6 6 l6 6 l6 -6">
<path d="M200 180.2 l-6 6 l6 6 l6 -6">
<path d="M240 180.2 l-6 6 l6 6 l6 -6">
<path d="M280 177.4 l-6 6 l6 6 l6 -6">
<path d="M320 180.3 l-6 6 l6 6 l6 -6">
<path d="M360 180.7 l-6 6 l6 6 l6 -6">
<path d="M400 200.7 l-6 6 l6 6 l6 -6">
<path d="M440 217.9 l-6 6 l6 6 l6 -6">
<path d="M480 217.9 l-6 6 l6 6 l6 -6">
<path d="M520 181.9 l-6 6 l6 6 l6 -6">
<path d="M560 180.3 l-6 6 l6 6 l6 -6">
<path d="M600 182 l-6 6 l6 6 l6 -6">
<path d="M640 180.9 l-6 6 l6 6 l6 -6">
</g>
<g fill="#FFC000">
<path d="M440 222.9 h40 v2 h-40" transform="rotate(-0,440,223.9)">
<path d="M480 222.9 h71 v2 h-71" transform="rotate(55.7,480,223.9)">
<path d="M520 281.6 h40 v2 h-40" transform="rotate(0.2,520,282.6)">
<path d="M560 281.8 h40 v2 h-40" transform="rotate(1.1,560,282.8)">
<path d="M600 282.6 h40 v2 h-40" transform="rotate(-0.3,600,283.6)">
<path d="M440 217.9 l-6 6 l6 6 l6 -6">
<path d="M480 217.9 l-6 6 l6 6 l6 -6">
<path d="M520 276.6 l-6 6 l6 6 l6 -6">
<path d="M560 276.8 l-6 6 l6 6 l6 -6">
<path d="M600 277.6 l-6 6 l6 6 l6 -6">
<path d="M640 277.4 l-6 6 l6 6 l6 -6">
</g>
</svg>
title
<$FIGURE>
図３　マルチバイト NOP 命令１サイクルあたりの実行数
end title
@enduml
```

# 結論

インテルは流石である。伊達にパフォーマンスが下がるようなコードは吐かない。いくらプリフィクスが付いていても uOPs キャッシュに入ってしまえば関係ないのだろう。

加えて，レジスタストール問題についても最近の Core プロセッサであれば（おそらく）起こらないのではないかと考える。というのも参考文献 [10] によれば，Sandy Bridge 以降の Core プロセッサには Zeroing Idioms という新機能が追加されたからだ。これは `xor eax, eax` とか `sub eax, eax` のような命令に適用される。これらの命令はレジスタの元の値に関係なく結果がゼロになるので依存関係は切れ，並列に実行できるようになる。

であれば，最近の Core プロセッサであれば，マルチバイト NOP 命令についても同様にストールを起こさないような工夫を施すことは簡単であろうし，実際に実現しているのではないかと思われる。

# もっと旧世代の Core プロセッサの場合

下記の環境でも調べてみた。

- intel Core i7-3770 プロセッサ 3.4GHz（最大 3.9GHz）, 16GB
- Windows 10 22H2

命令長 $n$，総実行時間 $t$，最大動作周波数 $\phi$ とおくと，並列実行数 $p$ は次の式で表される。

```math
p = \frac{400000000 \times \displaystyle\frac{1800}{n}}{t \times \phi}
```

<table>
<caption>表７　マルチバイト NOP 命令の総実行時間・並列実行数の比較</caption>
<thead>
<tr><th rowspan=2 style="text-align:center">コンパイラ</th>
    <th rowspan=2 style="text-align:center">長<br>さ</th>
    <th colspan=3 style="text-align:center">総実行時間（s）</th>
    <th colspan=3 style="text-align:center">並列実行数（個）</th></tr>
<tr><th style="text-align:center">i7-<br>12700</th>
    <th style="text-align:center">i5-<br>10400</th>
    <th style="text-align:center">i7-<br>3770</th>
    <th style="text-align:center">i7-<br>12700</th>
    <th style="text-align:center">i5-<br>10400</th>
    <th style="text-align:center">i7-<br>3770</th></tr>
</thead>
<tbody>
<tr><th rowspan=15>intel<br>C++<br>Compiler</th>
    <td style='text-align:right'>1</td>
    <td style='text-align:right'>26.099</td>
    <td style='text-align:right'>42.892</td>
    <td style='text-align:right'>46.788</td>
    <td style='text-align:right'>5.630</td>
    <td style='text-align:right'>3.904</td>
    <td style='text-align:right'>3.946</td></tr>
<tr><td style='text-align:right'>2</td>
    <td style='text-align:right'>12.664</td>
    <td style='text-align:right'>21.576</td>
    <td style='text-align:right'>23.424</td>
    <td style='text-align:right'>5.801</td>
    <td style='text-align:right'>3.880</td>
    <td style='text-align:right'>3.941</td></tr>
<tr><td style='text-align:right'>3</td>
    <td style='text-align:right'>9.316</td>
    <td style='text-align:right'>14.401</td>
    <td style='text-align:right'>15.611</td>
    <td style='text-align:right'>5.258</td>
    <td style='text-align:right'>3.876</td>
    <td style='text-align:right'>3.942</td></tr>
<tr><td style='text-align:right'>4</td>
    <td style='text-align:right'>6.223</td>
    <td style='text-align:right'>10.801</td>
    <td style='text-align:right'>11.710</td>
    <td style='text-align:right'>5.903</td>
    <td style='text-align:right'>3.876</td>
    <td style='text-align:right'>3.941</td></tr>
<tr><td style='text-align:right'>5</td>
    <td style='text-align:right'>5.006</td>
    <td style='text-align:right'>8.639</td>
    <td style='text-align:right'>9.432</td>
    <td style='text-align:right'>5.871</td>
    <td style='text-align:right'>3.876</td>
    <td style='text-align:right'>3.915</td></tr>
<tr><td style='text-align:right'>6</td>
    <td style='text-align:right'>4.146</td>
    <td style='text-align:right'>7.096</td>
    <td style='text-align:right'>7.805</td>
    <td style='text-align:right'>5.907</td>
    <td style='text-align:right'>3.933</td>
    <td style='text-align:right'>3.942</td></tr>
<tr><td style='text-align:right'>7</td>
    <td style='text-align:right'>3.545</td>
    <td style='text-align:right'>6.173</td>
    <td style='text-align:right'>6.691</td>
    <td style='text-align:right'>5.921</td>
    <td style='text-align:right'>3.875</td>
    <td style='text-align:right'>3.942</td></tr>
<tr><td style='text-align:right'>8</td>
    <td style='text-align:right'>3.109</td>
    <td style='text-align:right'>5.413</td>
    <td style='text-align:right'>6.006</td>
    <td style='text-align:right'>5.908</td>
    <td style='text-align:right'>3.867</td>
    <td style='text-align:right'>3.842</td></tr>
<tr><td style='text-align:right'>9</td>
    <td style='text-align:right'>2.768</td>
    <td style='text-align:right'>5.369</td>
    <td style='text-align:right'>6.013</td>
    <td style='text-align:right'>5.898</td>
    <td style='text-align:right'>3.465</td>
    <td style='text-align:right'>3.411</td></tr>
<tr><td style='text-align:right'>10</td>
    <td style='text-align:right'>2.509</td>
    <td style='text-align:right'>5.365</td>
    <td style='text-align:right'>6.009</td>
    <td style='text-align:right'>5.856</td>
    <td style='text-align:right'>3.121</td>
    <td style='text-align:right'>3.072</td></tr>
<tr><td style='text-align:right'>11</td>
    <td style='text-align:right'>2.277</td>
    <td style='text-align:right'>4.876</td>
    <td style='text-align:right'>6.119</td>
    <td style='text-align:right'>5.867</td>
    <td style='text-align:right'>3.122</td>
    <td style='text-align:right'>2.743</td></tr>
<tr><td style='text-align:right'>12</td>
    <td style='text-align:right'>2.089</td>
    <td style='text-align:right'>3.631</td>
    <td style='text-align:right'>6.016</td>
    <td style='text-align:right'>5.862</td>
    <td style='text-align:right'>3.843</td>
    <td style='text-align:right'>2.557</td></tr>
<tr><td style='text-align:right'>13</td>
    <td style='text-align:right'>1.931</td>
    <td style='text-align:right'>3.325</td>
    <td style='text-align:right'>6.006</td>
    <td style='text-align:right'>5.853</td>
    <td style='text-align:right'>3.874</td>
    <td style='text-align:right'>2.364</td></tr>
<tr><td style='text-align:right'>14</td>
    <td style='text-align:right'>1.816</td>
    <td style='text-align:right'>3.115</td>
    <td style='text-align:right'>6.012</td>
    <td style='text-align:right'>5.780</td>
    <td style='text-align:right'>3.840</td>
    <td style='text-align:right'>2.193</td></tr>
<tr><td style='text-align:right'>15</td>
    <td style='text-align:right'>1.738</td>
    <td style='text-align:right'>2.891</td>
    <td style='text-align:right'>6.016</td>
    <td style='text-align:right'>5.636</td>
    <td style='text-align:right'>3.861</td>
    <td style='text-align:right'>2.046</td></tr>
<tr><th rowspan=6>Microsoft<br>Visual<br>C++</th>
    <td style='text-align:right'>10</td>
    <td style='text-align:right'>2.496</td>
    <td style='text-align:right'>5.364</td>
    <td style='text-align:right'>6.016</td>
    <td style='text-align:right'>5.887</td>
    <td style='text-align:right'>3.122</td>
    <td style='text-align:right'>3.069</td></tr>
<tr><td style='text-align:right'>11</td>
    <td style='text-align:right'>2.276</td>
    <td style='text-align:right'>4.876</td>
    <td style='text-align:right'>6.015</td>
    <td style='text-align:right'>5.869</td>
    <td style='text-align:right'>3.122</td>
    <td style='text-align:right'>2.790</td></tr>
<tr><td style='text-align:right'>12</td>
    <td style='text-align:right'>4.140</td>
    <td style='text-align:right'>7.165</td>
    <td style='text-align:right'>7.831</td>
    <td style='text-align:right'>2.958</td>
    <td style='text-align:right'>1.947</td>
    <td style='text-align:right'>1.965</td></tr>
<tr><td style='text-align:right'>13</td>
    <td style='text-align:right'>3.814</td>
    <td style='text-align:right'>6.624</td>
    <td style='text-align:right'>7.255</td>
    <td style='text-align:right'>2.964</td>
    <td style='text-align:right'>1.944</td>
    <td style='text-align:right'>1.957</td></tr>
<tr><td style='text-align:right'>14</td>
    <td style='text-align:right'>3.567</td>
    <td style='text-align:right'>6.202</td>
    <td style='text-align:right'>6.741</td>
    <td style='text-align:right'>2.942</td>
    <td style='text-align:right'>1.928</td>
    <td style='text-align:right'>1.956</td></tr>
<tr><td style='text-align:right'>15</td>
    <td style='text-align:right'>3.313</td>
    <td style='text-align:right'>5.777</td>
    <td style='text-align:right'>6.276</td>
    <td style='text-align:right'>2.957</td>
    <td style='text-align:right'>1.932</td>
    <td style='text-align:right'>1.961</td></tr>
</tbody>
</table>

グラフは重なって見にくいので第10世代を省いた。第３世代も10バイト以下の特性は第10世代と変わらないが，11バイト以上になると並列実行数の緩やかな低下が見られる。

12バイト以上になると Microsoft Visual C++ コンパイラは２命令に分割して出力するため，第10世代以降では intel C++ コンパイラのちょうど半分に低下するが，第３世代はその差が少なく15バイトになると変わらなくなる。第３世代まで古くなると懸念されたプリフィクス使い過ぎ問題が発生するのか，もしくは命令長自体が無くなり過ぎると何らかのペナルティが起こるのかもしれない。

<font color="#5B9BD5">◆</font> Core i7-12700 intel C++ Compiler，<font color="#ED7D31">◆</font> Core i7-12700 Microsoft Visual C++
<font color="#3B64AD">◆</font> Core i7-3770 intel C++ Compiler，<font color="#92C96E">◆</font> Core i7-3770 Microsoft Visual C++

```plantuml
@startuml
<style>
root {
  padding 0
  margin 0
}
title {
  fontStyle normal
  fontSize 16
}
</style>
sprite FIGURE <svg width="700" height="440">
<g fill="lightgray">
<path d="M40 30 h640 v1 h-640">
<path d="M40 80 h640 v1 h-640">
<path d="M40 130 h640 v1 h-640">
<path d="M40 180 h640 v1 h-640">
<path d="M40 230 h640 v1 h-640">
<path d="M40 280 h640 v1 h-640">
<path d="M40 330 h640 v1 h-640">
<path d="M40 380 h640 v1 h-640">
<path d="M40 30 v350 h1 v-350">
<path d="M120 30 v350 h1 v-350">
<path d="M200 30 v350 h1 v-350">
<path d="M280 30 v350 h1 v-350">
<path d="M360 30 v350 h1 v-350">
<path d="M440 30 v350 h1 v-350">
<path d="M520 30 v350 h1 v-350">
<path d="M600 30 v350 h1 v-350">
<path d="M680 30 v350 h1 v-350">
</g>
<text x="40" y="20" font-size="16" fill="black">[個]</text>
<text x="25" y="36" font-size="16" fill="black">7</text>
<text x="25" y="86" font-size="16" fill="black">6</text>
<text x="25" y="136" font-size="16" fill="black">5</text>
<text x="25" y="186" font-size="16" fill="black">4</text>
<text x="25" y="236" font-size="16" fill="black">3</text>
<text x="25" y="286" font-size="16" fill="black">2</text>
<text x="25" y="336" font-size="16" fill="black">1</text>
<text x="25" y="386" font-size="16" fill="black">0</text>
<text x="36" y="400" font-size="16" fill="black">0</text>
<text x="116" y="400" font-size="16" fill="black">2</text>
<text x="196" y="400" font-size="16" fill="black">4</text>
<text x="276" y="400" font-size="16" fill="black">6</text>
<text x="356" y="400" font-size="16" fill="black">8</text>
<text x="430" y="400" font-size="16" fill="black">10</text>
<text x="510" y="400" font-size="16" fill="black">12</text>
<text x="590" y="400" font-size="16" fill="black">14</text>
<text x="670" y="400" font-size="16" fill="black">16</text>
<text x="310" y="420" font-size="16" fill="black">長さ[bytes]</text>
<g fill="#5B9BD5">
<path d="M80 97.5 h40.9 v2 h-40.9" transform="rotate(-12.1,80,98.5)">
<path d="M120 88.9 h48.4 v2 h-48.4" transform="rotate(34.2,120,89.9)">
<path d="M160 116.1 h51.4 v2 h-51.4" transform="rotate(-38.9,160,117.1)">
<path d="M200 83.8 h40 v2 h-40" transform="rotate(2.3,200,84.8)">
<path d="M240 85.5 h40 v2 h-40" transform="rotate(-2.6,240,86.5)">
<path d="M280 83.7 h40 v2 h-40" transform="rotate(-1,280,84.7)">
<path d="M320 82.9 h40 v2 h-40" transform="rotate(1,320,83.9)">
<path d="M360 83.6 h40 v2 h-40" transform="rotate(0.7,360,84.6)">
<path d="M400 84.1 h40.1 v2 h-40.1" transform="rotate(3,400,85.1)">
<path d="M440 86.2 h40 v2 h-40" transform="rotate(-0.7,440,87.2)">
<path d="M480 85.7 h40 v2 h-40" transform="rotate(0.4,480,86.7)">
<path d="M520 85.9 h40 v2 h-40" transform="rotate(0.6,520,86.9)">
<path d="M560 86.3 h40.2 v2 h-40.2" transform="rotate(5.3,560,87.3)">
<path d="M600 90 h40.6 v2 h-40.6" transform="rotate(10.1,600,91)">
<path d="M80 92.5 l-6 6 l6 6 l6 -6">
<path d="M120 83.9 l-6 6 l6 6 l6 -6">
<path d="M160 111.1 l-6 6 l6 6 l6 -6">
<path d="M200 78.8 l-6 6 l6 6 l6 -6">
<path d="M240 80.5 l-6 6 l6 6 l6 -6">
<path d="M280 78.7 l-6 6 l6 6 l6 -6">
<path d="M320 77.9 l-6 6 l6 6 l6 -6">
<path d="M360 78.6 l-6 6 l6 6 l6 -6">
<path d="M400 79.1 l-6 6 l6 6 l6 -6">
<path d="M440 81.2 l-6 6 l6 6 l6 -6">
<path d="M480 80.7 l-6 6 l6 6 l6 -6">
<path d="M520 80.9 l-6 6 l6 6 l6 -6">
<path d="M560 81.3 l-6 6 l6 6 l6 -6">
<path d="M600 85 l-6 6 l6 6 l6 -6">
<path d="M640 92.2 l-6 6 l6 6 l6 -6">
</g>
<g fill="#ED7D31">
<path d="M440 84.7 h40 v2 h-40" transform="rotate(1.3,440,85.7)">
<path d="M480 85.5 h151 v2 h-151" transform="rotate(74.6,480,86.5)">
<path d="M520 231.1 h40 v2 h-40" transform="rotate(-0.4,520,232.1)">
<path d="M560 230.8 h40 v2 h-40" transform="rotate(1.5,560,231.8)">
<path d="M600 231.9 h40 v2 h-40" transform="rotate(-1,600,232.9)">
<path d="M440 79.7 l-6 6 l6 6 l6 -6">
<path d="M480 80.5 l-6 6 l6 6 l6 -6">
<path d="M520 226.1 l-6 6 l6 6 l6 -6">
<path d="M560 225.8 l-6 6 l6 6 l6 -6">
<path d="M600 226.9 l-6 6 l6 6 l6 -6">
<path d="M640 226.2 l-6 6 l6 6 l6 -6">
</g>
<g fill="#3B64AD">
<path d="M80 181.7 h40 v2 h-40" transform="rotate(0.4,80,182.7)">
<path d="M120 182 h40 v2 h-40" transform="rotate(-0.1,120,183)">
<path d="M160 181.9 h40 v2 h-40" transform="rotate(0,160,182.9)">
<path d="M200 181.9 h40 v2 h-40" transform="rotate(1.9,200,182.9)">
<path d="M240 183.3 h40 v2 h-40" transform="rotate(-2,240,184.3)">
<path d="M280 181.9 h40 v2 h-40" transform="rotate(0,280,182.9)">
<path d="M320 181.9 h40.3 v2 h-40.3" transform="rotate(7.1,320,182.9)">
<path d="M360 186.9 h45.4 v2 h-45.4" transform="rotate(28.3,360,187.9)">
<path d="M400 208.4 h43.4 v2 h-43.4" transform="rotate(23,400,209.4)">
<path d="M440 225.4 h43.3 v2 h-43.3" transform="rotate(22.4,440,226.4)">
<path d="M480 241.9 h41.1 v2 h-41.1" transform="rotate(13.1,480,242.9)">
<path d="M520 251.1 h41.1 v2 h-41.1" transform="rotate(13.5,520,252.1)">
<path d="M560 260.8 h40.9 v2 h-40.9" transform="rotate(12.1,560,261.8)">
<path d="M600 269.3 h40.7 v2 h-40.7" transform="rotate(10.5,600,270.3)">
<path d="M80 176.7 l-6 6 l6 6 l6 -6">
<path d="M120 177 l-6 6 l6 6 l6 -6">
<path d="M160 176.9 l-6 6 l6 6 l6 -6">
<path d="M200 176.9 l-6 6 l6 6 l6 -6">
<path d="M240 178.3 l-6 6 l6 6 l6 -6">
<path d="M280 176.9 l-6 6 l6 6 l6 -6">
<path d="M320 176.9 l-6 6 l6 6 l6 -6">
<path d="M360 181.9 l-6 6 l6 6 l6 -6">
<path d="M400 203.4 l-6 6 l6 6 l6 -6">
<path d="M440 220.4 l-6 6 l6 6 l6 -6">
<path d="M480 236.9 l-6 6 l6 6 l6 -6">
<path d="M520 246.1 l-6 6 l6 6 l6 -6">
<path d="M560 255.8 l-6 6 l6 6 l6 -6">
<path d="M600 264.3 l-6 6 l6 6 l6 -6">
<path d="M640 271.7 l-6 6 l6 6 l6 -6">
</g>
<g fill="#92C96E">
<path d="M440 225.6 h42.4 v2 h-42.4" transform="rotate(19.2,440,226.6)">
<path d="M480 239.5 h57.5 v2 h-57.5" transform="rotate(45.9,480,240.5)">
<path d="M520 280.8 h40 v2 h-40" transform="rotate(0.5,520,281.8)">
<path d="M560 281.1 h40 v2 h-40" transform="rotate(0.1,560,282.1)">
<path d="M600 281.2 h40 v2 h-40" transform="rotate(-0.3,600,282.2)">
<path d="M440 220.6 l-6 6 l6 6 l6 -6">
<path d="M480 234.5 l-6 6 l6 6 l6 -6">
<path d="M520 275.8 l-6 6 l6 6 l6 -6">
<path d="M560 276.1 l-6 6 l6 6 l6 -6">
<path d="M600 276.2 l-6 6 l6 6 l6 -6">
<path d="M640 275.9 l-6 6 l6 6 l6 -6">
</g>
</svg>
title
<$FIGURE>
図４　マルチバイト NOP 命令１サイクルあたりの実行数
end title
@enduml
```

# おまけ

今回の検証に用いたソースコード一式を以下に示す。

<details><summary><b>x86 アセンブラ部のソースはコチラ</b></summary>

すっごい久しぶりにアセンブラのコードを書いたわ。

```:NOPS.ASM
        .MODEL  FLAT
        .CODE
;-------------------------------------------------------------------------------
        PUBLIC  _nop1
_nop1   PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  1800
        DB      90h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop1   ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop2
_nop2   PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  900
        DB      66h, 90h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop2   ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop3
_nop3   PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  600
        DB      0Fh, 1Fh, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop3   ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop4
_nop4   PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  450
        DB      0Fh, 1Fh, 40h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop4   ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop5
_nop5   PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  360
        DB      0Fh, 1Fh, 44h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop5   ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop6
_nop6   PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  300
        DB      66h, 0Fh, 1Fh, 44h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop6   ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop7
_nop7   PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  257
        DB      0Fh, 1Fh, 80h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop7   ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop8
_nop8   PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  225
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop8   ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop9
_nop9   PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  200
        DB      66h
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop9   ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop10
_nop10  PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  180
        DB      66h, 2Eh
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop10  ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop11
_nop11  PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  164
        DB      66h, 66h, 2Eh
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop11  ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop12
_nop12  PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  150
        DB      66h, 66h, 66h, 2Eh
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop12  ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop13
_nop13  PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  138
        DB      66h, 66h, 66h, 66h, 2Eh
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop13  ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop14
_nop14  PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  129
        DB      66h, 66h, 66h, 66h, 66h, 2Eh
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop14  ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop15
_nop15  PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  120
        DB      66h, 66h, 66h, 66h, 66h, 66h, 2Eh
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop15  ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop10a
_nop10a PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  180
        DB      66h, 66h
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop10a ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop11a
_nop11a PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  164
        DB      66h, 66h, 66h
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop11a ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop12a
_nop12a PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  150
        DB      0Fh, 1Fh, 40h, 00h
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop12a ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop13a
_nop13a PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  138
        DB      0Fh, 1Fh, 40h, 00h
        DB      66h
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop13a ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop14a
_nop14a PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  129
        DB      0Fh, 1Fh, 40h, 00h
        DB      66h, 66h
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop14a ENDP
;-------------------------------------------------------------------------------
        PUBLIC  _nop15a
_nop15a PROC
        mov     ecx, 400000000
        ALIGN   16
@@:
        REPEAT  120
        DB      0Fh, 1Fh, 40h, 00h
        DB      66h, 66h, 66h
        DB      0Fh, 1Fh, 84h, 00h, 00h, 00h, 00h, 00h
        ENDM
        dec     ecx
        jnz     @b
        ret
_nop15a ENDP
;-------------------------------------------------------------------------------
        END
```

</details>

<details><summary><b>C言語部のソースはコチラ</b></summary>

```c++:TEST.C
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
extern	void	nop1( void );
extern	void	nop2( void );
extern	void	nop3( void );
extern	void	nop4( void );
extern	void	nop5( void );
extern	void	nop6( void );
extern	void	nop7( void );
extern	void	nop8( void );
extern	void	nop9( void );
extern	void	nop10( void ); extern	void	nop10a( void );
extern	void	nop11( void ); extern	void	nop11a( void );
extern	void	nop12( void ); extern	void	nop12a( void );
extern	void	nop13( void ); extern	void	nop13a( void );
extern	void	nop14( void ); extern	void	nop14a( void );
extern	void	nop15( void ); extern	void	nop15a( void );
int	main(int argc, char*argv[]) {
	if(argc < 2) {
		fprintf(stderr, "Usage: test(.exe) [nops]\n");
		return -1;
	}
	char	*s = argv[1];
	void	(*func)(void) =
		!strcmp(s, "1") ? nop1 :
		!strcmp(s, "2") ? nop2 :
		!strcmp(s, "3") ? nop3 :
		!strcmp(s, "4") ? nop4 :
		!strcmp(s, "5") ? nop5 :
		!strcmp(s, "6") ? nop6 :
		!strcmp(s, "7") ? nop7 :
		!strcmp(s, "8") ? nop8 :
		!strcmp(s, "9") ? nop9 :
		!strcmp(s, "10") ? nop10 : !strcmp(s, "10a") ? nop10a :
		!strcmp(s, "11") ? nop11 : !strcmp(s, "11a") ? nop11a :
		!strcmp(s, "12") ? nop12 : !strcmp(s, "12a") ? nop12a :
		!strcmp(s, "13") ? nop13 : !strcmp(s, "13a") ? nop13a :
		!strcmp(s, "14") ? nop14 : !strcmp(s, "14a") ? nop14a :
		!strcmp(s, "15") ? nop15 : !strcmp(s, "15a") ? nop15a :
		NULL;
	if(func == NULL) {
		fprintf(stderr, "illegal option: %s\n", s);
		return -1;
	}
	clock_t	t1 = clock();
	(*func)();
	clock_t	t2 = clock();
	fprintf(stdout, "time: %.3f\n", (double)(t2 - t1) / CLOCKS_PER_SEC);
	return 0;
}
```

</details>

<details><summary><b>メイクファイルはコチラ</b></summary>

```:Makefile
target: TEST.EXE

TEST.EXE: TEST.OBJ NOPS.OBJ
	link $** /DEBUG:NONE /OUT:$@

.C.OBJ:
	cl /c /O2 /W4 /GS- $<

.ASM.OBJ:
	ml /c $<

clean:
	if exist *.OBJ del *.OBJ
	if exist *.EXE del *.EXE
```

</details>

<details><summary><b>テスト用バッチファイルはコチラ</b></summary>

```:GOGO.CMD
@echo off
for %%I in (
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  10a 11a 12a 13a 14a 15a
) do (
  echo %%I
  start /b /w /realtime test %%I
)
exit /b
```

</details>

# 参考文献

1. [x86_64 機械語入門 - githubio](https://tanakamura.github.io/pllp/docs/x8664_language.html)
2. [Intel 64 and IA-32 Architectures Software Developer’s Manual - intel](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html)
3. [nop命令のオペランド - Qiita](https://qiita.com/Kinmedayu/items/b66ddba0cf95e3369716)
4. [色々なNOPコード - 黒翼猫のコンピュータ日記 3rd Edition](https://win2k.org/blog/2011/12/27/1598318/)
5. [何もしない長い命令、マルチバイト NOP (x86/x64) - やや低レイヤー研究所](https://yaya.lsv.jp/multibyte-nop/)
6. [インテル 64 および IA-32 アーキテクチャー最適化リファレンス・マニュアル参考訳 Volume 1 - iSUS <img width="16" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490655/66e66c9d-a6f3-f215-951a-9d79cc94a9d6.png">](https://www.isus.jp/wp-content/uploads/pdf/64-ia-32-architectures-optimization-manual-vol1_JA.pdf)
7. [インテル 64 および IA-32 アーキテクチャー最適化リファレンス・マニュアル参考訳 Volume 2: 旧世代のインテル 64 および IA-32 プロセッサー・アーキテクチャー、スループット、およびレイテンシー - iSUS <img width="16" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490655/66e66c9d-a6f3-f215-951a-9d79cc94a9d6.png">](https://www.isus.jp/wp-content/uploads/pdf/64-ia-32-architectures-optimization-manual-vol2_JA.pdf)
8. [Intel、次期CPU「Alder Lake」に搭載される新コアの詳細を発表 - PC Watch](https://pc.watch.impress.co.jp/docs/news/1344892.html)
9. [あなたの知らないnopたち@ラボユース合宿 - slideshare](https://www.slideshare.net/slideshow/nop-79146911/79146911)
10. [第221回 コンピュータアーキテクチャの話 ダイナミック電力の低減手法(4) - マイナビ](https://news.mynavi.jp/techplus/article/architecture-221/)
11. [高性能コンピュータ技術の基礎，Hisa Ando，マイナビ出版，2011年6月](https://book.mynavi.jp/ec/products/detail/id=22500)
12. [NOP WORD PTR? - Qiita](https://qiita.com/jkr_2255/items/eaca341a80df845ef667)
13. [nop命令のオペランド - Qiita](https://qiita.com/Kinmedayu/items/b66ddba0cf95e3369716)