Assembly Language & x86 Low-Level Systems Programming · レッスン

分岐予測と投機的実行

最新のCPUが分岐を予測して投機的に実行し、レイテンシを隠す仕組みを学びます。予測ミスによるサイクル数の損失や、副作用から生まれたSpectre系攻撃についても扱います。

レッスン 4/413 ステップ

「分岐予測と投機的実行」はCoddyKit上の無料Assembly Language & x86 Low-Level Systems Programmingレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAssembly Language & x86 Low-Level Systems Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Assembly Language & x86 Low-Level Systems Programmingコースには全4レッスンが含まれています。

このレッスンの一部はまだ翻訳されておらず、英語で表示されています。

The Pipeline Problem

Modern CPUs are deeply pipelined, fetching and decoding many instructions ahead. But a conditional branch is a fork: the CPU does not yet know which path to fetch. Stalling would waste the whole pipeline.

Branch Prediction

To avoid stalls the CPU predicts which way a branch will go and keeps fetching. If correct, no time is lost. If wrong, the pipeline is flushed — a costly misprediction penalty of 15-20+ cycles.

How Predictors Learn

The Branch Target Buffer and history tables record past outcomes. A simple 2-bit saturating counter remembers whether a branch was recently taken, predicting that loops keep looping.

Speculative Execution

Beyond predicting, the CPU speculatively executes the predicted path before the condition resolves. If the guess holds, results are committed; if not, they are discarded as if they never ran — architecturally.

Writing Predictable Branches

You help the predictor by making branches consistent. A branch that is almost always taken predicts well; a random branch defeats prediction. Sorting data before a conditional loop can dramatically speed it up.

for (int i = 0; i < n; i++)
    if (data[i] >= 128)   // predictable only if data is sorted
        sum += data[i];

A Runnable Benchmark

This C program shows the dramatic effect of sorted vs unsorted data on a branch-heavy loop. Run it and compare timings.

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int n = 32768;
    int *d = malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) d[i] = rand() % 256;
    long sum = 0;
    for (int r = 0; r < 1000; r++)
        for (int i = 0; i < n; i++)
            if (d[i] >= 128) sum += d[i];
    printf("sum=%ld\n", sum);
    free(d);
    return 0;
}

Branchless Programming

You can sometimes eliminate a branch entirely with arithmetic or conditional-move instructions (cmov), so the CPU never needs to predict.

cmp eax, 128
cmovge ebx, ecx   ; conditionally move, no branch to mispredict

Likely/Unlikely Hints

Compilers expose hints like __builtin_expect (the source of likely()/unlikely() macros) so hot paths fall through and cold paths jump away, improving instruction-cache layout.

if (__builtin_expect(error, 0)) {
    handle_error();   // marked cold/unlikely
}

The Security Side Effect

Speculative results are discarded architecturally — but they leave traces in the cache. Speculatively loaded data warms cache lines, and that timing difference can be measured. This is the basis of side-channel leaks.

Spectre in a Nutshell

Spectre tricks the predictor into speculatively reading memory it should not, then leaks the value through a cache timing side channel. The reads never commit, so they bypass normal bounds checks during the speculation window.

Mitigations

Defenses include serializing instructions (lfence) to stop speculation past a bounds check, retpolines for indirect branches, and microcode updates. They trade some performance for safety.

cmp index, limit
jae out_of_range
lfence            ; block speculation past the check

Quick Check

Test your understanding of speculation.

Recap

You learned how CPUs hide branch latency:

  • Branch prediction guesses the path; mispredicts cost a pipeline flush
  • Speculative execution runs the predicted path early
  • Predictable branches, cmov, and likely/unlikely hints boost speed
  • Speculation leaves cache side effects exploited by Spectre; lfence and retpolines mitigate it
無料で開始

AI チューターと学ぶ Assembly — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
12
レッスン
48

よくある質問

「分岐予測と投機的実行」レッスンは無料ですか?

はい。「分岐予測と投機的実行」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Assembly Language & x86 Low-Level Systems Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Assembly Language & x86 Low-Level Systems Programmingコースには全4レッスンが含まれています。

「分岐予測と投機的実行」で何を学びますか?

最新のCPUが分岐を予測して投機的に実行し、レイテンシを隠す仕組みを学びます。予測ミスによるサイクル数の損失や、副作用から生まれたSpectre系攻撃についても扱います。 ブラウザで直接実行するハンズオンコードでAssembly Language & x86 Low-Level Systems Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Assembly Language & x86 Low-Level Systems Programmingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAssembly Language & x86 Low-Level Systems Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「分岐予測と投機的実行」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAssembly Language & x86 Low-Level Systems Programmingレッスンでコードを書いて実行できますか?

はい。すべてのAssembly Language & x86 Low-Level Systems Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. キャッシュコヒーレンシーとパフォーマンス
  2. クリティカルセクションの手動最適化
  3. バッファーオーバーフローとシェルコード
  4. 分岐予測と投機的実行
← Assembly Language & x86 Low-Level Systems Programmingに戻る