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

x86アーキテクチャ 編集

x86アーキテクチャは、インテルが開発したマイクロプロセッサのアーキテクチャです。1978年に最初のx86プロセッサであるIntel 8086が登場して以来、x86アーキテクチャはPCおよび互換機市場で非常に広く普及しています。

このアーキテクチャは、以下のような特徴を持っています。

命令セット
x86アーキテクチャは複数の命令セットを組み合わせています。初期のバージョンから現在のx86-64まで、多くの命令が追加され、命令セットが拡張されてきました。
互換性
x86プロセッサは、過去のアーキテクチャとの互換性を保持しています。これは、古いソフトウェアやシステムが新しいx86プロセッサで動作することを可能にしています。
アドレッシングモード
x86アーキテクチャは複数のアドレッシングモードを持ち、メモリアクセスやデータ処理の柔軟性を提供しています。
セグメンテーション
x86ではセグメンテーションと呼ばれるメモリ管理方式が存在します。初期のx86ではセグメンテーションが主要なメモリアクセス方法でしたが、後のバージョンではページングなどの手法がより一般的になりました。
多様な用途
x86アーキテクチャは、パーソナルコンピュータからサーバ、組み込みシステムまで、様々な用途で利用されています。その柔軟性と互換性から、多くの機器やシステムで採用されています。

x 86アーキテクチャの進化は、コンピューティングの発展に大きな影響を与え、広範な利用と成長を支えています。

レジスタ構成 編集

x86アーキテクチャのレジスタ構成は時間の経過とともに変化してきました。主な変遷を見てみましょう。

8086(16ビット)
8086プロセッサは16ビットアーキテクチャで、次のようなレジスタを持っていました。
  • データレジスタ: AX, BX, CX, DX
  • インデックスレジスタ: SI (Source Index), DI (Destination Index)
  • ポインタレジスタ: BP (Base Pointer), SP (Stack Pointer)
  • セグメントレジスタ: CS (Code Segment), DS (Data Segment), ES (Extra Segment), SS (Stack Segment)
  • その他の制御レジスタ
80386(32ビット)
80386プロセッサでは、レジスタが32ビットに拡張されました。
  • データレジスタ: 32ビットに拡張されたEAX、EBX、ECX、EDX
  • 32ビットに拡張されたESI、EDI、EBP、ESP
  • セグメントレジスタ: CS、DS、ESと追加されたFS、GS、SS
  • その他の制御レジスタ
x86-64(64ビット)
x86-64(またはAMD64)では、64ビットアーキテクチャに拡張され、新しいレジスタが追加されました。
  • データレジスタ: 64ビットに拡張されたRAX、RBX、RCX、RDXと新設されたR8、R9、R10、R11、R12、R13、R14、R15の8つの64ビットレジスタ
  • 64ビットに拡張されたRSI、RDI、RBP、RSP
  • セグメントレジスタ: CS、DS、ESと追加されたFS、GS、SS

x86アーキテクチャは、ビット幅の拡張に伴い、レジスタのビット幅も拡張され、本数も増えました。 これにより、より大きなデータを処理し、大容量のメモリを効率的に操作できるようになりました。

フラグレジスタ 編集

x86アーキテクチャにおけるフラグレジスタは、命令の実行結果やプロセッサの状態を示すための特別なレジスタです。各世代のx86アーキテクチャにおける主要なフラグレジスタの変遷を見てみましょう。

8086(16ビット)
8086プロセッサでは、主要なフラグレジスタとして次のようなものがありました。
  • Carry Flag (CF): 符号なし演算における桁上がりを示す
  • Zero Flag (ZF): 結果がゼロかどうかを示す
  • Sign Flag (SF): 結果の符号を示す
  • Overflow Flag (OF): 符号付き演算におけるオーバーフローを示す
  • Parity Flag (PF): 結果の下位8ビットのパリティ(1の数が偶数か奇数か)を示す
80386(32ビット)
32ビットの80386プロセッサでは、フラグレジスタには追加のフラグが導入されましたが、基本的なフラグは変わりませんでした。

x86-64(64ビット):x86-64アーキテクチャでも基本的なフラグは同様ですが、追加の命令や拡張により、さらに多くのフラグが利用可能になりました。例えば、AMD64拡張では、追加のフラグが導入されていますが、基本的なフラグの役割は変わりません。

命令ポインタ 編集

x86アーキテクチャにおける命令ポインタは、プログラムの次に実行すべき命令のメモリアドレスを示すレジスタです。このポインタは、プログラムカウンタ(Program Counter, PC)とも呼ばれます。これまでのx86アーキテクチャにおける命令ポインタの変遷を見てみましょう。

8086(16ビット)
8086プロセッサでは、16ビットの命令ポインタが使用されていました。この命令ポインタは、プログラムの次の実行命令のメモリアドレスを保持していました。
80386(32ビット)
32ビットの80386プロセッサでは、命令ポインタも32ビットに拡張されました。これにより、より広いアドレス空間を扱うことができるようになりました。
x86-64(64ビット)
x86-64アーキテクチャでも、命令ポインタは64ビットに拡張され、さらに広範なアドレス空間を扱うことが可能になりました。

命令ポインタは、プログラムの実行中に次に実行すべき命令のメモリアドレスを指し示すため、アーキテクチャの進化とともにアドレスの幅も拡張されてきました。これにより、より大きな物理メモリ空間にアクセスできるようになり、より大規模なプログラムを実行できるようになりました。

メモリ 編集

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

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

リトルエンディアンでの表現
B0 B1 B2 B3

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

リトルエンディアンの例
D4 83 A5 1B

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

命令セットの特徴 編集

x86とx64(またはAMD64)の命令セットは、それぞれ独自の特徴と利点を持っています。

x86の命令セットの特徴
32ビットアーキテクチャ
x86は32ビットのアーキテクチャであり、32ビットのレジスタや32ビットのアドレス空間を持っています。これは主に、物理メモリアドレスが32ビット幅までしかアクセスできないことに由来しています。
レジスタとアドレッシングモード
x86のレジスタはEAX、EBX、ECX、EDXなどの32ビットレジスタです。また、複数のアドレッシングモードが利用可能で、効率的なメモリアクセスが可能です。
命令セットの拡張
x86の命令セットは、SSE(Streaming SIMD Extensions)やMMXなどの浮動小数点演算の拡張を含んでいます。
x64(AMD64)の命令セットの特徴
64ビットアーキテクチャ
x64は64ビットのアーキテクチャで、より大きな物理メモリアドレス空間にアクセスできます。これにより、複数のギガバイトのメモリにアクセスできます。
レジスタ
x64では64ビットのレジスタ(RAX、RBX、RCX、RDXなど)が追加され、64ビット整数演算をサポートしています。
命令セットの拡張
x64にはSSEやAVXなどの拡張命令セットが含まれており、浮動小数点演算などの高度な演算を行うのに便利です。
追加の汎用レジスタと命令
x64では追加の汎用レジスタとともに新しい命令が導入され、パフォーマンスの向上や64ビットアーキテクチャの利点を最大限に引き出すための機能が追加されました。

これらの違いにより、x86とx64はそれぞれ異なる用途や要件に対応しています。x64の64ビットアーキテクチャは、より大きな物理メモリにアクセスできるため、大規模なデータ処理やメモリ集約型のアプリケーションに適しています。一方で、x86の32ビットアーキテクチャは、リソースが制限された環境や古いシステムのサポートに有用です。

x86の命令長とプリフィックス

x86アーキテクチャにおける命令の長さは可変です。命令のバイナリ表現は様々な長さになりますが、典型的なx86の命令は1バイトから始まり、オプコードと呼ばれる命令の主要部分を示します。この後に追加のバイト(オプショナルなプリフィックスやオペランドなど)が続く場合があります。

プリフィックスは、命令の挙動や動作モードを変更するための追加のバイトです。これらはオペランドのサイズを変更したり、セグメントレジスタを指定したり、アドレッシングモードを変更したりするのに使われます。

例えば、命令の先頭に 0x66 プリフィックスが付加されると、オペランドのサイズが変更され、16ビットから32ビットへと変わります。同様に、セグメントを指定するためのプリフィックスとして 0x67 が使用されます。

プリフィックスは、命令のバイナリ表現を拡張するため、全体としての命令の長さを増やす可能性があります。しかし、これらの追加のバイトは命令の主要部分であるオプコードに対するものであり、プリフィックスは特定の動作を追加するためのものです。

アドレッシングモード 編集

x86アーキテクチャには、複数のアドレッシングモードがあります。これらのモードは、CPUがメモリ内のデータや命令にアクセスする方法を定義します。以下に一般的なx86のアドレッシングモードをいくつか挙げて解説します。

レジスタアドレッシング
最も基本的なアドレッシングモードの一つで、データへのアクセスにレジスタを使用します。例えば、次のようなコードが該当します。
MOV AX, BX
この場合、BXレジスタの内容をAXレジスタにコピーする命令です。
即値アドレッシング:
命令そのものに直接値を指定してアクセスする方法です。例えば、次のようなコードが該当します。
MOV AX, 1234h
この場合、1234h(16進数)がAXレジスタに直接ロードされます。
直接メモリアドレッシング
MOV AX, [0080h]
0080h番地からAXレジスタに読み込まれる
レジスタ関節アドレッシング
MOV AX, [BX]
BXの示す番地からAXレジスタに読み込まれる
ディスプレースメント付きレジスタ間接アドレッシング
レジスタに格納されたアドレスにオフセット(ディスプレースメント)を加えて、その場所のメモリにアクセスする方法です。例えば、次のようなコードが該当します。
MOV AX, [BX + 4]
この場合、BXレジスタの内容に4を加えたアドレスのメモリからデータをAXレジスタにロードします。
ベースレジスタとインデックスレジスタを用いたアドレッシング
ベースレジスタとインデックスレジスタにそれぞれの値を格納し、それらを組み合わせてメモリアドレスを計算します。例えば、次のようなコードが該当します。
MOV AX, [BX + SI]
この場合、BXとSIレジスタの値を足して得られるアドレスのメモリからデータをAXレジスタにロードします。

これらのアドレッシングモードは、x86アーキテクチャで広く使用される基本的なものです。プログラムがメモリ内のデータや命令にアクセスする際に、これらのモードが使われます。


x86アーキテクチャにおけるアドレッシングモードは、時代とともに進化してきました。

主な変遷を以下に示します。

初期のx86(8086、8088など)
初期のx86プロセッサは、基本的なアドレッシングモードをサポートしており、レジスタ間接アドレッシングや即値アドレッシングが主流でした。ディスプレースメントアドレッシングや基底レジスタとインデックスレジスタを用いたアドレッシングモードも存在しましたが、制限されていました。
80386以降
80386プロセッサ以降のx86世代では、アドレッシングモードが大幅に拡張されました。新たなアドレッシングモードとして、スケールドインデックスモードやベースレジスタとインデックスレジスタの加算や減算によるアドレッシング、複雑なメモリ演算などが追加されました。これにより、より柔軟なメモリアクセスが可能になりました。
x86-64(AMD64)
x86-64アーキテクチャの導入により、より多くのレジスタや拡張されたアドレッシングモードが利用可能になりました。64ビットアーキテクチャにおいて、さらに大容量のメモリにアクセスするためのアドレッシングモードが提供されました。これは大規模なデータ処理や高速なアクセスに役立ちます。

x86アーキテクチャの進化に伴い、新たなレジスタや複雑なアドレッシングモードが導入され、プログラマがより柔軟にメモリにアクセスできるようになりました。この進化は、高度なアプリケーションや処理能力向上に貢献しています。

スタック 編集

x86アーキテクチャにおけるスタックは、メモリ内の特定領域であり、主にサブルーチンの呼び出しやローカル変数の格納など、プログラム実行中に一時的なデータを管理するのに使われます。スタックはLIFO(Last In, First Out)の原則に基づいており、最後に追加されたデータが最初に取り出されます。

x86のスタックは次の特徴を持っています:

スタックポインタ(SP)とベースポインタ(BP)
スタックの先頭アドレスを指し示すスタックポインタ(SP)と、スタック内の特定の場所を指すベースポインタ(BP)があります。SPは通常、新しいデータの追加や削除時に自動的に変化します。一方、BPはサブルーチン内のローカル変数のアクセスなどに使用されることがあります。
PUSHとPOP命令
x86アーキテクチャには、スタック操作のためのPUSH(プッシュ)およびPOP(ポップ)命令があります。PUSH命令はスタックにデータをプッシュし、POP命令はスタックからデータをポップします。
スタックフレーム
x86アーキテクチャでは、関数が呼び出されたときに作成されるスタックフレームと呼ばれる領域があります。これには、ローカル変数、関数の引数、リターンアドレスなどが含まれます。BPレジスタがスタックフレームの先頭を指すことが一般的です。
スタックの成長方向
x86では、スタックは通常、メモリの高いアドレスから低いアドレスの方向に成長します。つまり、新しいデータがスタックにプッシュされると、スタックポインタは低いアドレス方向に移動します。

スタックは、関数の呼び出しや戻り、一時的なデータの保持など、プログラム実行中の様々な操作に広く利用される重要なメモリ構造です。


i80186で追加されたENTERLEAVEは、x86アセンブリ言語で使用されるスタック操作のための命令です。

  1. ENTER:
    • ENTER命令は、スタックフレームを作成します。主にサブルーチンのプロローグで使用され、ローカル変数のためのスタック領域を確保します。
    • ENTER命令は次のような構造になっています:
    • sizeはローカル変数の合計サイズを指定し、nesting_levelはスタックフレームのネストレベルを指定します。
    • この命令は、ローカル変数領域の確保とスタックポインタの調整を行います。
  2. LEAVE:
    • LEAVE命令は、スタックフレームを破棄します。主にサブルーチンのエピローグで使用され、スタックフレームを解放します。
    • LEAVE命令は、ENTER命令で確保されたスタックフレームを解放するために使用されます。
    • 典型的なLEAVE命令は次のようになります:
    • この命令は、スタックフレームの解放とスタックポインタの調整を行います。

ENTERおよびLEAVE命令は、x86アセンブリ言語においてサブルーチンでのスタック操作を簡略化し、スタックフレームの作成と解放を効率的に行うための手段です。ただし、最近のコンパイラでは、これらの命令はあまり使用されず、代わりにより最適化された手法が採用されることがあります。

BP(Base Pointer)はx86アーキテクチャのレジスタの一つで、主にスタックフレーム内での相対的なアドレス計算に使用されます。BPレジスタは通常、現在のスタックフレームのベースアドレスを指す役割を果たします。

BPレジスタには次のような役割があります:

  1. スタックフレームへのアクセス:
    • BPレジスタは、特にサブルーチン(関数やプロシージャ)内でのローカル変数や引数、以前のスタックフレームへのアクセスに利用されます。通常、スタックフレームの先頭を指し示すことが多いです。
  2. 相対アドレス指定:
    • BPをベースにして相対的なアドレス指定が行えます。例えば、[BP+4]のように記述すると、BPレジスタが指すアドレスから4バイト後ろのアドレスを指定します。
  3. デバッグ目的:
    • デバッガにおいて、BPレジスタはスタックフレームの特定のアドレスに対するアクセスを容易にします。デバッグ時にローカル変数や関数の引数へのアクセスに使用されることがあります。

一般的に、BPレジスタはサブルーチン内でのスタックフレームのアクセスや相対的なアドレス指定に利用されます。しかし、最近のコンパイラは最適化や高度なアセンブリ生成により、BPの利用を最小限に抑え、スタックフレームのアクセスにはより効率的な方法を採用することがあります。

x86アーキテクチャにおけるスタックフレームは、関数(サブルーチンやプロシージャ)が実行される際に、ローカル変数、引数、戻りアドレスなどの情報を格納するメモリ領域です。スタックフレームは、関数呼び出し時にスタック上に動的に生成され、関数の実行が終了すると破棄されます。 典型的なx86アーキテクチャにおけるスタックフレームの構造は以下のような形です: リターンアドレス: 関数が終了した後に戻るべき次の命令のアドレスを示す値が格納されます。通常、関数呼び出し前にプログラムカウンタの値(次に実行される命令のアドレス)がスタックにプッシュされます。 ベースポインタ(BP): スタックフレーム内での相対的なアドレス指定のために使用されるベースポインタが含まれます。BPは通常、現在のスタックフレームの始めを指し示します。 ローカル変数: 関数内で定義されたローカル変数や一時的な変数がスタックフレーム内に確保されます。これらの変数は通常、BPレジスタを基準に相対的な位置に配置されます。 引数: 関数に渡された引数もスタックフレーム内に格納されます。引数は通常、関数のプロローグでスタックにプッシュされます。 スタックフレームの構造は、コンパイラの呼び出し規約によって異なる場合があります。一般的な規約には、引数の受け渡し方法、スタックのクリーンアップ方法、レジスタの使用方法などが含まれます。これらの規約は、関数呼び出し時にスタックフレームの構築と解放を効率的に行うために使用されます。

CPUの動作モード 編集

x86プロセッサは、複数の動作モードを持っています。代表的な動作モードとしては以下のものがあります:

リアルモード(Real Mode)
16ビットのアドレス空間を使い、古いソフトウェアや古いOSとの互換性を保つためのモードです。このモードでは、セグメントとオフセットを使ってアドレスを生成します。
プロテクトモード(Protected Mode)
32ビット(または64ビット)のアドレス空間を利用できるモードです。メモリの保護やセキュリティ、複数のプロセスの同時実行を可能にします。このモードでは、セグメントとページングの機能を使用します。
ロングモード(Long Mode)
x86-64(64ビット)プロセッサに特有のモードで、64ビットのアドレス空間を使用します。これにより、大容量のメモリアクセスや64ビットプログラムの実行が可能になります。プロテクトモードの拡張版と見なすことができます。

これらのモードは、x86プロセッサが古いソフトウェアから最新のOSやアプリケーションまで様々な環境で動作できるようにするために存在します。各モードは異なる特性やアドレス空間を持ち、特定の目的に応じて適切なモードが選択されます。例えば、リアルモードは古いソフトウェアとの互換性を維持するために、プロテクトモードやロングモードは現代のOSやアプリケーションの要求に応えるために使用されます。

リアルモード 編集

x86アーキテクチャのリアルモードは、古いコンピューターシステムやソフトウェアとの互換性を保つために存在するモードの一つです。ここでは、その主な特徴や機能を解説します。

16ビットリアルモード
リアルモードは、x86プロセッサの16ビットモードの一種です。このモードでは、セグメントとオフセットの組み合わせによって物理メモリをアクセスします。
セグメントとオフセットの組み合わせによって、物理メモリのアドレスを生成します。具体的には、セグメントレジスタの値を左に4ビットシフトしてからオフセットを足し合わせます。
セグメントとオフセット
リアルモードでは、物理メモリへのアクセスはセグメントとオフセットの組み合わせで行われます。セグメントは64KBのサイズを持ち、オフセットはその範囲内でメモリアクセスを行います。
この方式は、物理メモリを16ビットのアドレス空間に区切り、それぞれのセグメントが重なり合うことなく一意のアドレスを参照できるようにします。
リアルモードの制約
リアルモードでは、セグメンテーションとオフセットの制限から、扱えるメモリ空間が64KB×64KB(約1MB)に限られます。これはアドレスの計算方法に由来する制約で、古いアプリケーションやOSがこの範囲内で動作するように設計されています。
プロテクトモードへの移行
リアルモードからプロテクトモード(32ビットや64ビットモード)への移行には、特定の手順が必要です。プロテクトモードでは、より大容量のメモリにアクセスでき、セグメントとオフセットによる制限がなくなります。
リアルモードは、古いソフトウェアやBIOS互換性のために利用されることがありますが、現代のOSやアプリケーションではプロテクトモードやロングモードなどのより進化したモードが利用されています。

プロテクトモード 編集

x86プロセッサのプロテクトモードは、Intel 80386プロセッサ以降のx86アーキテクチャで採用された一種の動作モードです。このモードでは、メモリ保護や特権レベルの管理など、より高度なセキュリティとマルチタスク処理が可能になります。

プロテクトモードでは、以下のような特徴があります:

メモリ保護
プロセスが使用するメモリを保護するための仕組みがあります。これにより、異なるプロセスが互いのメモリ空間にアクセスできないようになります。
特権レベル
特権レベルが0から3まであり、0が最高特権(カーネルモード)で、3が最低特権(ユーザーモード)です。プロセスはユーザーモードで実行され、特権的なタスクはカーネルモードで実行されます。これにより、システムの安定性やセキュリティが向上します。
セグメンテーションとページング: メモリアクセスを制御するためのセグメンテーションとページングの機能が提供されます。これにより、物理メモリの管理が向上し、効率的なメモリ利用が可能になります。

プロテクトモードは、より高度な操作やセキュリティを実現するために重要な機能を提供しますが、操作がより複雑になるため、実装や管理には注意が必要です。

x86のプロテクトモードでは、メモリの管理において、セグメンテーションとページングという2つの主要な仕組みがあります。

  1. セグメンテーション(Segmentation):
    • セグメンテーションは、メモリを論理的なブロックで分割する仕組みです。各プロセスは複数のセグメント(コード、データ、スタックなど)を持ち、それぞれが特定の属性やサイズを持ちます。
    • セグメントはセグメント・ディスクリプタと呼ばれるデータ構造で表され、ベースアドレスやセグメントの長さなどの情報を含んでいます。
    • セグメンテーションはメモリの保護や論理的な区切りを提供しますが、効率的なメモリ管理を行うためにページングと組み合わせて使用されることがあります。
  2. ページング(Paging):
    • ページングは、物理メモリを固定サイズのページに分割する技術です。論理アドレスと物理アドレスの間のマッピングを行い、必要に応じて物理メモリを仮想メモリにマップします。
    • ページングにより、物理メモリの断片化を最小限に抑えつつ、効率的なメモリ管理や保護が可能になります。
    • ページングはセグメンテーションと組み合わせて使用され、多くの場合、ページングがセグメンテーションよりも優先される傾向があります。

これらの仕組みを組み合わせることで、プロテクトモードにおいて効率的なメモリ管理と保護を実現します。

フラットメモリモデルとマルチセグメントメモリモデルは、x86アーキテクチャにおけるメモリのアクセスや管理の方法を表す異なるモデルです。

  1. フラットメモリモデル:
    • フラットメモリモデルでは、プログラムが単一の連続したアドレス空間を使って動作すると仮定します。これは、セグメントの概念を無視し、物理メモリ上でのプログラムの実行を一連の連続したメモリ領域として扱います。
    • セグメントの切り替えや管理が不要なため、プログラムの記述が簡単になります。しかし、セグメントの特性を利用できないため、セキュリティやメモリの保護などの面で制限があります。
  2. マルチセグメントメモリモデル:
    • マルチセグメントメモリモデルでは、プログラムやデータを複数のセグメントに分割し、それぞれに異なる特性や属性を持たせます。例えば、コード、データ、スタックなどの異なる機能を持つセグメントを使います。
    • セグメントを使うことで、メモリの保護やセキュリティを向上させることができます。また、複数のプロセスが同時に実行される場合、それぞれのプロセスが異なるセグメント内で動作することが可能です。

フラットメモリモデルは単純で理解しやすい反面、セグメントの特性を最大限に活用できません。一方、マルチセグメントメモリモデルはセグメントの特性を利用してセキュリティや保護を高めることができますが、管理が複雑になりがちです。プロテクトモードにおいて、これらのモデルを選択する際には、それぞれの利点と欠点を考慮する必要があります。

x86(32)アーキテクチャにおいて、Linuxカーネルはフラットメモリモデルを採用しています。これは、メモリが単一の連続したアドレス空間として扱われることを意味します。同様に、FreeBSDなどBSD系のUNIX、macOS、Windows11などNT系のWindowsもフラットメモリモデルを採用しています。

ロングモデル 編集

x86のロングモードは、64ビットプロセッサの機能を活用するためのモードです。これは、32ビットのプロテクトモードの拡張版であり、64ビットのアドレッシングをサポートします。 主な特徴は以下のとおりです:

64ビットアドレス空間
ロングモードでは、64ビットのアドレス空間が利用可能です。これにより、理論上は2の64乗(約18エクサバイト)の物理メモリアクセスが可能となります。
64ビットレジスタと命令セット
ロングモードでは、追加の64ビットレジスタ(RAX、RBX、RCXなど)が利用可能になります。また、新しい64ビットの命令セット(AMD64またはx86-64)も導入されます。
モードの切り替え
通常、プロセッサはブート時にリアルモードからスタートし、その後プロテクトモードへ移行します。その後、64ビットOSがロングモードに切り替えます。これは、64ビットOSが必要とする新しい機能やリソースにアクセスするためのものです。

ロングモードは、32ビットのプロテクトモードよりも大容量のメモリアクセスや64ビットアプリケーションの実行を可能にします。これにより、より高性能なアプリケーションやOSが開発され、より大規模なメモリや処理能力を必要とするアプリケーションが実行されるようになりました。

x86とx64の差異
x86とx64(またはAMD64と呼ばれる)は、IntelとAMDが開発した異なる命令セットアーキテクチャです。これらにはいくつかの主な違いがあります。
アドレス空間
x86アーキテクチャは32ビットのアドレス空間を持ち、通常4GBまでの物理メモリにアクセスできます。一方、x64アーキテクチャは64ビットのアドレス空間を持ち、これにより非常に大きな物理メモリを扱えます。
レジスタ
x86アーキテクチャには通常、汎用レジスタがEAX、EBX、ECX、EDXなどの32ビットレジスタとして存在します。一方、x64アーキテクチャでは、より多くの汎用レジスタ(RAX、RBX、RCX、RDXなど)が64ビットレジスタとして使用されます。
命令セット
x64アーキテクチャでは、追加の命令セットや拡張が提供されています。これにより、新しい命令や拡張された命令が利用可能になり、パフォーマンスの向上や64ビットアーキテクチャを活かした新しい機能の実装が可能になります。
レジスタを用いた引数の渡し方
x86アーキテクチャではスタックを主に利用して引数を渡しますが、x64アーキテクチャではレジスタを使って最初の数個の引数を渡すことが一般的です。
システムコール
x86とx64ではシステムコールの呼び出し方法が異なります。x86ではINT命令を使って呼び出されますが、x64ではSYSCALL命令が使われます。
浮動小数点演算
x64アーキテクチャでは、拡張された浮動小数点演算命令セット(SSEやAVXなど)が使用され、より効率的な浮動小数点演算が可能です。x64である時点で、SSEが実装されていることを仮定できます。MMXどころかx86では80x87の存在すら仮定できません。

これらは一般的な違いですが、各アーキテクチャはその独自の特徴と利点を持ち、プログラムのパフォーマンスや機能を最大限に引き出すために利用されます。