PEEKとPOKE

コンピューティングにおいて、PEEK英語で「チラッと見る」の意味。}}とPOKE英語で「突く」の意味。}}は、いくつかの高水準プログラミング言語で使用されるコマンドで、メモリーアドレスで参照される特定のメモリセルの内容にアクセスするために使用する。BASICのものがよく知られているが、PascalやCOMALなど他のプログラミング言語にも同様のコマンドがある。このコマンドは、C言語などにおけるポインタに匹敵する役割を持っている。

PEEKとPOKEは、初期のパーソナルコンピュータにおいて様々な目的を果たすために考案され、特に、メモリ空間にマッピングされたハードウェアレジスタを変更するために使用された。また、プログラマはこのコマンドを使用して、ソフトウェアをコピーしたり、特定のソフトウェアのプログラミングの意図を回避したりすることもある。今日では、BASICのような高水準言語を使用して、低水準でメモリを制御することはあまりなく、PEEK、POKEというコマンドの概念は一般的に時代遅れとみなされている。

英語においては、//peek//や//poke//という言葉が、プログラミングにおけるメモリアクセスを指す動詞として口語的に使われることがある。

1. 文法
-----

PEEK関数とPOKEコマンドは、通常、以下のように直接モードか、間接モードで呼び出される。 integer_variable = PEEK

POKE address, value<WtXmlEndTag /> 引数の//address//と//value//は、評価される式がそれぞれ有効なメモリアドレスまたは値に対応する限り、複雑な式を含んでいても良い。ここで言う「有効なアドレス」とは、コンピュータのアドレス空間内のアドレスであり、「有効な値」とは、ゼロから最小アドレス可能なユニットが保持することができる最大符号なし数までの符号なし値である。

2. メモリセルとハードウェアレジスタ
-------------------

POKEまたはPEEKされるアドレス位置は、通常のメモリセルや、対応するチップのメモリマップされたハードウェアレジスタ、CPU自体のメモリマップされたレジスタを参照することができる。以下は、POKEによる対応チップ制御の一例として、コモドール64の内蔵MOS Technology VIC-IIグラフィックスチップの特定のレジスタを操作して、画面の境界線を黒くするコマンドの例である。

POKE 53280, 0

以下は、Atari 8ビット・コンピュータでANTICディスプレイドライバに、全てのテキストを上下逆さまにするように指示するコマンドである。

POKE 755, 4

ハードに紐付けられたメモリ位置は機種によって異なるため、様々な機種の「メモリマップ」は重要な文書である。定型的な例として、アタリのコンピュータの64キロバイトのメモリ全体をロケーションごとにマッピングした本『マッピング・オブ・アタリ』が出版されている。

一般的に、ユーザプログラム、ユーザデータ、オペレーティングシステムのコードとデータ、メモリマップされたハードウェアユニットのために指定されたメモリアドレス領域は、機種によって異なる。このため、PEEK関数やPOKEコマンドは本質的に非移植性であり、これらを使用したプログラムは、そのプログラムが書かれたシステム以外ではほぼ確実に動作しない。

3. チートとしてのPOKE
--------------

多くの8ビットコンピュータ用ゲームにおいては、ゲームをメモリにロードし、起動する前に特定のメモリアドレスを変更して、無制限のライフ、無敵化、敵からの不可視化などのチートを行うことができた。このような変更は、POKEコマンドを使って行われた。コモドール64、ZX Spectrum、Amstrad CPCでは、関連するカートリッジやMultifaceを持っているプレイヤーは、実行中のプログラムをフリーズさせてPOKEを入力し、チート状態で再開することもできた。

例えば、ZX Spectrum向けの『ナイト・ロアー』では、以下のコマンドで無敵化することができた。

POKE 47196, 201

この場合、値201はRET命令に相当するので、衝突判定をトリガーする前に、ゲームがサブルーチンから早期に復帰する。

『ユア・シンクレア』などの雑誌には、ゲームにおけるそのようなPOKEコマンドが掲載されていた。このようなコードは、一般的に、機械語コードをリバースエンジニアリングして、ライフ数、衝突の検出などに関連するメモリアドレスを識別することで発見されていた。

POKEによるチートの使用は、最近のゲームでは難しくなっている。最近のオペレーティングシステムは、外部プログラムからの非共有メモリへのアクセスができないようするために、仮想記憶化によるメモリ保護を行っている。

4. 16ビットマシンのPEEKとPOKE
---------------------

初期のBASICが動作するほとんどのコンピュータは8ビットプロセッサを使用していたため、1つのPEEKまたはPOKEの値は0から255の間のものだった。16ビットマシンにおいて16ビットの整数値を読み書きするには、PEEKやPOKEを2回実施する必要がある。アドレスAの16ビット整数値を読み出すためには、2=basicとする必要があり、アドレスAに16ビット整数Vを書き込むためには、2=basicに続けて2=basicを実行する必要がある。

IBM PCやAmigaなどの16・32ビットマシンでは、16ビット値を一度に読み書きできるDPEEKやDPOKEのようなコマンドが公式で用意されていた。Sinclair QLでは、16・32ビット値の読み書きができるPEEK_W/PEEK_L、POKE_W/POKE_Lコマンドがあった。Atari STシリーズでは、コマンド名称は8ビットのコマンドと同様だが、読み書きするビット幅を指定することができた。また、いくつかの8ビットマシンには、16ビット幅のPEEKとPOKEを行うBASIC方言があった。例えば、東ドイツの"Kleincomputer" KC85/1やKC87には、DEEK、DOKEコマンドがあった。

5. その他のBASICのPEEKとPOKE
----------------------

1980年代初期のベンダーであるノーススター・コンピューターズは、独自のBASIC方言・North Star BASICを持つオペレーティングシステム・NSDOSを使用していたが、法的問題の懸念から、コマンド名をEXAMとFILLに変更していた。他に、MEMWとMEMRを代わりに使用するBASIC方言もあった。

BBC Microやその他のエイコーン・コンピュータのマシンで使用されたBBC BASICでは、PEEKやPOKEというキーワードはなく、//query//と呼ばれる疑問符を関数とコマンドの両方の操作に使用していた。以下にその例を示す。

> DIM W% 4 : REM 4バイトのメモリを確保し、整数型変数 W% で指定する。 > ?W% = 42 : REM 定数 42 を格納する。これは'POKE W%, 42'と等価である。 > PRINT ?W% : REM W% が指すバイトを表示する。これは'PRINT PEEK'と等価である。 42

32ビット値は、//pling//と呼ばれる感嘆符を使用して、最下位バイトを最初にして、PEEKやPOKEを実施することができる。さらに、アドレスの後にqueryかplingのいずれかを指定して、オフセット値を指定してアドレスをオフセットすることもできる。

> !W% = &12345678 : REM アンパサントは16進数であることを意味する。 > PRINT ~?W%, ~W%?3 : REM チルダは16進数として表示する。 78 12

文字列は、ドル記号を使用して同様の方法でPEEKやPOKEを行うことができる。文字列の終端は、キャリッジリターン文字で示される。オフセットは、ドル記号では使用できない。

> DIM S% 20 : REM 20バイトのメモリを確保し、 S% で指定する。 > $S% = "MINCE PIES" : REM 文字列'MINCE PIES'を格納する。文字列は &0D で終端されている。 > PRINT $ : REM S% + 6バイトから始まる &0D で区切られた文字列を表示する。 PIES

6. "POKE"という言葉の使用法
------------------

"POKE"という言葉は、特に1970年代後半から1980年代初頭にかけて8ビットコンピュータでプログラムを学んだ人々の間で、BASICを介したもの以外も含めて、「メモリの内容を直接操作すること」の意味で使用されることがある。

Visual Basic for Windowsでは、DDEを実現するのにLinkPokeキーワードを使用する。

8ビットビデオゲームのチートはPOKEと呼ばれることもあった。

7. 脚注
-----

7.1. 注釈
-------

7.2. 出典
-------

8. 関連項目
-------

自己書き換えコード
ポインタ