メモリアドレス
メモリアドレス(memory address)は、コンピュータの主記憶装置にアクセスするためにソフトウェアおよびハードウェアによって様々なレベルで使用されるデータ概念である。通常、メモリアドレスは、符号あり・符号なし整数として表示・処理される固定長の数字の列である。メモリアドレスの数値の意味は、CPUの機能(プログラムカウンタやメモリアドレスレジスタなど)や様々なプログラミング言語で採用されている配列のようなメモリの使用法に基づいている。
デジタルコンピュータのメモリ、より詳細には主記憶装置(メインメモリ)は、多数のメモリロケーション(memory location)からなり、それぞれのメモリロケーションは、CPUや他の装置がそれにアクセスするために使用する物理アドレス(physical address)を有する。一般に、システムソフトウェア(すなわちBIOS)、オペレーティングシステム、および特定のユーティリティプログラム(メモリテスタなど)だけが、プログラムのコマンドを実行するために、機械語のオペランドやレジスタにおいて物理メモリを使用し、CPUからメモリコントローラと呼ばれるハードウェアデバイスに対して、メモリバスやシステムバスを使用するか、あるいは制御バス、アドレスバス、データバスを分離するよう指示を出す。メモリコントローラのバスは、それぞれ1桁の二進数(ビット)を表す複数のパラレルな通信線からなる。バスの幅はコンピュータによって異なり、したがってアドレス指定可能なメモリユニットの数、および各ユニットのビット数も、コンピュータによって異なる。
コンピュータプログラムは、メモリアドレスを使用して機械語を実行し、データを記憶・検索する。初期のコンピュータでは、論理アドレスと物理アドレスは対応していた。仮想記憶の導入以降、ほとんどのアプリケーションソフトウェアは、物理アドレスを使用せず論理アドレス(仮想アドレス空間)でアドレス指定し、コンピュータのメモリ管理ユニットとオペレーティングシステムのメモリマッピングで物理アドレスに変換される。下記を参照。
現代のバイトアクセスのコンピュータでは、アドレスはメモリ中の1バイトを識別する。そのため、1バイトに格納するには大きすぎるデータは連続したアドレスを占める複数のバイトに格納されることになる。ワードアクセスとして設計されたマイクロプロセッサでは標準的な記憶単位(ワード)は1バイトより大きくなる。例えば、データゼネラルのNova、テキサス・インスツルメンツのTMS9900、ナショナル セミコンダクターのIMP-16は16ビットワードを使用し、多くの36ビットメインフレーム(PDP-10など)は、18ビットワードを使用し、36ビットワードで218個ののアドレス空間、約1メガバイトの記憶域を使用できた。
メモリのアドレス指定の効率は、アドレスに使用されるバスのビットサイズに依存する。使用されるビットが多いほど、コンピュータで使用できるアドレスが増える。例えば、20ビットのアドレスバスを有する8ビットバイトアドレス可能なマシン(Intel 8086など)は、220(=1,048,576)個のメモリロケーション、1 MiBのメモリをアドレス指定することができる。32ビットバス(Intel 80386など)では232(= 4,294,967,296)個のメモリロケーション、4 GiBのアドレス空間をアドレス指定することができる。 18ビットアドレスバスを備えた36ビットワードアドレス可能マシンでは、1,179,648バイト(= 1,152 KB = 1.125 MiB = 9,437,184ビット)に相当する218(= 262,144)個のメモリロケーションが指定可能であり、8086よりわずかに多い。
古いコンピュータの一部(十進数コンピュータ)は、十進数の数字でアドレス指定可能だった。例えば、IBM 1620の磁気コア・メモリの各アドレスは、パリティビット、フラグビット、および4つの数値ビットからなる単一の6ビット二進化十進数を識別した。1620は5桁の十進アドレスを使用していたため、理論上の最高可能アドレスは99,999だった。実際には、CPUは20,000のメモリロケーションをサポートし、オプションの外部メモリユニットを2つまで追加することができ、それぞれ20,000アドレスをサポートしたので、合計60,000(00000–59999)になった。
ワードサイズは、コンピュータアーキテクチャによって異なる。ワードサイズは、CPUが一度に処理できる桁数を表す。組込みシステムを含む最新のプロセッサは、通常、8ビット、16ビット、24ビット、32ビット、64ビットのワードサイズを有する。 最新の汎用コンピュータは32ビットまたは64ビットを使用する。歴史的には、8ビット、9ビット、10ビット、12ビット、18ビット、24ビット、36ビット、39ビット、40ビット、48ビット、60ビットなど、さまざまなサイズのワードが使用されていた。
現代のコンピュータのワードサイズは、そのコンピュータにおけるのアドレス空間のサイズも記述される。例えば、「32ビット」と言われるコンピュータにおいては、通常32ビットのメモリアドレスが使用される。バイトアドレス指定可能な32ビットコンピュータは、232 = 4,294,967,296バイトのメモリ、すなわち4ギビビット(GiB)をアドレス指定することができる。これにより、1つのメモリアドレスを効率的に1ワードに格納することができる。
しかし、これは必ずしも正しいとは限らない。コンピュータは、ワードサイズよりも大きい、あるいは小さいメモリアドレスを持つことができる。例えば、MOS 6502などの多くの8ビットプロセッサでは16ビットアドレスがサポートされていたが、そうでない場合はわずか256バイトのメモリアドレス指定に制限されていた。16ビットのIntel 8088とIntel 8086はセグメンテーションによる20ビットアドレス指定をサポートしており、64 KiBメモリではなく1 MiBにアクセスできる。Pentium Pro以降の全てのIntel Pentiumプロセッサには、36ビット物理アドレスから32ビット仮想アドレスへのマッピングをサポートする物理アドレス拡張(PAE)が含まれている。
理論上は、現代のバイトアクセス可能な64ビットコンピュータは264バイト(16エクスビバイト)に対応することができるが、実際にはメモリの量はCPU、メモリコントローラ、プリント回路基板の設計(物理メモリコネクタの数や実装されたメモリの量)によって制限される。
プログラム内蔵方式のコンピュータ内の各メモリロケーションは、「何らかの」二進数または十進数を保持する。保持された値をどう解釈するか(データ型のデータとしてあるいは命令として)、およびどのように使用するかは、それを取り出して操作する命令によって決定される。
初期のプログラマの中には、メモリを節約する方法として、命令とデータを1つのワードの中に組み合わせた者もいた。Manchester Mark Iは、40ビットワードの中にデータを格納するスペースを持っていた。プロセッサはワードの途中でデータセクションを無視した。それはしばしば追加のデータストレージとして利用されていたOctober 2011。
コンピュータウイルスのような自己複製プログラムは、時にはデータとして、時には命令として扱われる。自己書き換えコードは、今日では一般には非推奨とされている。これは、テストやメンテナンスが困難であり、コンピュータの状態 (計算機科学)に関するコンパイラやプロセッサの前提によって間違った結果をもたらす可能性があるためである。現在でも細心の注意を払って意図的に使用されることはある。
現代のマルチタスク環境では、アプリケーションのプロセスは通常、そのアドレス空間に以下のタイプのメモリチャンクを持っている。
以下の内容を含む機械語
プログラム自体のコード(歴史的にはコードセグメントと呼ばれる)
以下のものを含むデータ
初期化データ(データセグメント)
アドレス空間の一部は、全くマッピングされないこともある。
コンピュータプログラムは、明示的に指定されたアドレスにアクセスすることができる。低水準言語ではこれは絶対アドレス(absolute address)と呼ばれ、高水準言語ではポインタデータ型として知られている。また、プログラムは相対アドレスを使用して、ベースアドレスを基準としてアドレスを指定することもできる。他のも、多くの間接アドレッシングモードがある。
論理アドレスを物理メモリと仮想メモリにマッピングすることで、いくつかのレベルの間接参照も追加される。
多くのプログラマは、コードスペースとデータスペース(上記を参照)、物理メモリと仮想メモリの区別がないようにメモリをアドレス指定することを好む。つまり、数値的に同じポインタは、 RAM上で正確に同じバイトになる。
しかし、初期のコンピュータの多くは、このようなフラットメモリモデルをサポートしていなかった。特に、ハーバード・アーキテクチャでは、プログラム領域とデータ領域を完全に分離する必要があった。最新の多くのDSP(Motorola 56000など)には、プログラム記憶域、係数記憶域、データ記憶域の3つの独立した記憶領域がある。一般的に使用される命令の中には、3つの領域すべてから同時にフェッチするものがあり、記憶領域の合計バイト数が同じであっても、記憶領域が少なければ、命令の実行が遅くなる。
初期のx86コンピュータは、メモリセグメントとそのセグメント内のオフセットという2つの数字の組み合わせに基づく、セグメント方式のアドレスを使用していた。一部のセグメントは、命令、スタックセグメント、または通常のデータセグメント専用のコードセグメントとして暗黙的に扱われていた。用途は異なっていたが、セグメントにはこれを反映した異なるメモリ保護がなかった。フラットメモリモデルでは、全てのセグメント(セグメントレジスタ)は一般に0に設定され、オフセットのみが可変である。