(57)【要約】【課題】暗号化に頼らずにプログラムの解析を困難にする仕組みを提供する。【解決手段】命令表１０には、命令と、その命令に対応する機械語のオペコードと、そのオペコードがその命令を意味するためにそのオペコードの配置先のアドレスが持つべき特徴と、の対応関係が保持される。プログラム保護装置１２は、命令表１０に従い、原プログラム１４中の命令をオペコードに変換し、そのオペコードの配置先アドレスを決定する。この処理により生成される保護済みプログラム１６中のオペコードは、そのオペコードが置かれたアドレスに応じてその意味（どの命令を表しているか）が変わる。プログラム実行装置１８は、保護済みプログラム１６から読み出したオペコードと、そのオペコードが置かれていたアドレスとの組合せから、命令表１０に従ってそのオペコードの意味を特定し、その意味に応じた演算を実行する。【選択図】図１
2016057991.tif 000002
【特許請求の範囲】
【請求項１】
機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段と、
原プログラム中の命令を機械語の命令コードに変換する変換手段であって、当該命令の変換先の命令コードと、当該命令コードの配置先のアドレスが持つ特徴と、前記原プログラム中の前記命令が表す演算処理と、が前記対応関係を満たすよう、前記変換先の命令コードと前記配置先のアドレスとを定める変換手段、を有するプログラム保護装置と、
機械語のプログラムからから読み出した命令コードとこの命令コードのアドレスが持つ特徴との組合せに対応する演算処理を、前記保持手段が保持する前記対応関係に従って特定し、特定した演算処理を実行する実行手段、を有するプログラム実行装置と、
を備える情報処理システム。
【請求項２】
アドレスが持つ前記特徴は、２のべき乗を法とする前記アドレスの剰余であることを特徴とする、請求項１に記載の情報処理システム。
【請求項３】
機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段と、
原プログラム中の命令を機械語の命令コードに変換する変換手段であって、当該命令の変換先の命令コードと、当該命令コードの配置先のアドレスが持つ特徴と、前記原プログラム中の前記命令が表す演算処理と、が前記保持手段に保持された前記対応関係を満たすよう、前記変換先の命令コードと前記配置先のアドレスとを定める変換手段と、
を有するプログラム保護装置。
【請求項４】
コンピュータを、
機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段、
原プログラム中の命令を機械語の命令コードに変換する変換手段であって、当該命令の変換先の命令コードと、当該命令コードの配置先のアドレスが持つ特徴と、前記原プログラム中の前記命令が表す演算処理と、が前記保持手段に保持された前記対応関係を満たすよう、前記変換先の命令コードと前記配置先のアドレスとを定める変換手段、
として機能させるためのプログラム。
【請求項５】
機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段と、
機械語のプログラムからから読み出した命令コードとこの命令コードのアドレスが持つ特徴との組合せに対応する演算処理を、前記保持手段が保持する前記対応関係に従って特定し、特定した演算処理を実行する実行手段と、
を有する保護済みプログラム実行装置。
【請求項６】
コンピュータを、
機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段、
機械語のプログラムからから読み出した命令コードとこの命令コードのアドレスが持つ特徴とに対応する演算処理を、前記保持手段が保持する前記対応関係に従って特定し、特定した演算処理を実行する実行手段、
として機能させるためのプログラム。
【請求項７】
前記保持手段及び前記実行手段が、前記読み出した命令コードとこの命令コードのアドレスが持つ特徴との組合せに対応する演算処理が、アドレスの特徴による条件分岐と前記命令コードによる条件分岐との組合せにより選択され実行されるように構成されたプログラムコードとして実装されていることを特徴とする請求項６に記載のプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、情報処理システム、プログラム保護装置、プログラム実行装置及びプログラムに関する。
【背景技術】
【０００２】
コンピュータで実行されるコード内に含まれる秘密を秘匿するため、または、コードを改竄されないために、そのコードを独自の仮想マシン（仮想のＣＰＵ）の命令で記述する方式が知られている。この方式では、仮想マシンの命令で記述したコードを実際のコンピュータ（ネイティブ環境）でエミュレーション実行することで、コード解析を難しくする。
【０００３】
また仮想マシン（以下「ＶＭ」と略す。ＶＭはVirtual Machineの略）上で動作する(例えばJava（登録商標）で記述された)コードを暗号化しておき、実際のコンピュータでの実行前にそのコードを復号してから実行する方法も知られている。
【０００４】
また特許文献１には、プログラムのうち保護対象の部分は暗号化して保護すると共に、実行時には復号してＶＭ上で動作するようにし、保護対象でない部分についてはネイティブ環境で実行する方法が開示されている。
【０００５】
特許文献２には、無許可のプログラムコード改変を防止するために、アドレスビットを使用して、システムメモリに記憶されているデータの暗号化および／または保護を可能にするシステムが開示されている。このシステムでは、アドレスラインのうち少なくとも１本は、暗号化機構が、データをメモリに記憶する前に暗号化し、メモリから取り出した後に復号化できるようにする。もう１本のアドレスラインは、保護機構がデータのハッシュを生成できるようにする。ハッシュは、データがシステムメモリに記憶されている間に改変されたかどうかを判定するために記憶され使用される。特許文献２のシステムでは、アドレスに従ってセキュリティ機能のオンオフ制御を可能にしている。
【先行技術文献】
【特許文献】
【０００６】
【特許文献１】特開２０１３−２００８３１号公報
【特許文献２】特開２００６−６５８５１号公報
【発明の概要】
【発明が解決しようとする課題】
【０００７】
プログラムを暗号化して保護したとしても、実行時には復号が必要である。したがって、実行時に復号されたプログラムがデバッガ等により解析されるおそれがある。デバッグ防止技術と組み合わせることでデバッガによる解析を防ぐことも考えられるが、検出困難なデバッガやＩＣＥ（In-Circuit Emulator）が存在しているので、復号されたプログラムをデバッガ等で解析される脅威は依然として残る。
【０００８】
本発明は、暗号化に頼らずにプログラムの解析を困難にする仕組みを提供することを目的とする。
【課題を解決するための手段】
【０００９】
請求項１に係る発明は、機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段と、原プログラム中の命令を機械語の命令コードに変換する変換手段であって、当該命令の変換先の命令コードと、当該命令コードの配置先のアドレスが持つ特徴と、前記原プログラム中の前記命令が表す演算処理と、が前記対応関係を満たすよう、前記変換先の命令コードと前記配置先のアドレスとを定める変換手段、を有するプログラム保護装置と、機械語のプログラムからから読み出した命令コードとこの命令コードのアドレスが持つ特徴との組合せに対応する演算処理を、前記保持手段が保持する前記対応関係に従って特定し、特定した演算処理を実行する実行手段、を有するプログラム実行装置と、を備える情報処理システムである。
【００１０】
請求項２に係る発明は、アドレスが持つ前記特徴は、２のべき乗を法とする前記アドレスの剰余であることを特徴とする、請求項１に記載の情報処理システムである。
【００１１】
請求項３に係る発明は、機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段と、原プログラム中の命令を機械語の命令コードに変換する変換手段であって、当該命令の変換先の命令コードと、当該命令コードの配置先のアドレスが持つ特徴と、前記原プログラム中の前記命令が表す演算処理と、が前記保持手段に保持された前記対応関係を満たすよう、前記変換先の命令コードと前記配置先のアドレスとを定める変換手段と、を有するプログラム保護装置である。
【００１２】
請求項４に係る発明は、コンピュータを、機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段、原プログラム中の命令を機械語の命令コードに変換する変換手段であって、当該命令の変換先の命令コードと、当該命令コードの配置先のアドレスが持つ特徴と、前記原プログラム中の前記命令が表す演算処理と、が前記保持手段に保持された前記対応関係を満たすよう、前記変換先の命令コードと前記配置先のアドレスとを定める変換手段、として機能させるためのプログラムである。
【００１３】
請求項５に係る発明は、機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段と、機械語のプログラムからから読み出した命令コードとこの命令コードのアドレスが持つ特徴との組合せに対応する演算処理を、前記保持手段が保持する前記対応関係に従って特定し、特定した演算処理を実行する実行手段と、を有する保護済みプログラム実行装置である。
【００１４】
請求項６に係る発明は、コンピュータを、機械語の命令コードと、アドレスが持つ特徴と、前記命令コードが前記特徴を持つアドレスに置かれた場合に前記命令コードが表す演算処理と、の対応関係を保持する保持手段、機械語のプログラムからから読み出した命令コードとこの命令コードのアドレスが持つ特徴とに対応する演算処理を、前記保持手段が保持する前記対応関係に従って特定し、特定した演算処理を実行する実行手段、として機能させるためのプログラムである。
【００１５】
請求項７に係る発明は、前記保持手段及び前記実行手段が、前記読み出した命令コードとこの命令コードのアドレスが持つ特徴との組合せに対応する演算処理が、アドレスの特徴による条件分岐と前記命令コードによる条件分岐との組合せにより選択され実行されるように構成されたプログラムコードとして実装されていることを特徴とする請求項６に記載のプログラムである。
【発明の効果】
【００１６】
請求項１、３〜７に係る発明によれば、暗号化に頼らずにプログラムの解析を困難にすることができる。
【００１７】
請求項２に係る発明によれば、プログラム保護装置により生成された機械語のプログラムをプログラム実行装置が実行する際、ページングによりそのプログラムがメモリ上のどのページにマッピングされても、アドレスの持つ特徴の計算に調整を加える必要がない。
【図面の簡単な説明】
【００１８】
【図１】実施形態におけるプログラムの難読化、及び難読化したプログラムの実行のための全体システムの例を示す図である。
【図２】プログラム保護装置が実行する処理の手順の例を示す図である。
【図３】プログラム実行装置が実行する処理の手順の例を示す図である。
【図４】プログラム実行装置の内部構成の一例を示す図である。
【図５】具体例として用いる命令の形式を説明するための図である。
【図６】アドレスの特徴としてそのアドレスの法４に関する剰余を用いる場合の、剰余０に対応する命令表の例を示す図である。
【図７】アドレスの特徴としてそのアドレスの法４に関する剰余を用いる場合の、剰余１に対応する命令表の例を示す図である。
【図８】アドレスの特徴としてそのアドレスの法４に関する剰余を用いる場合の、剰余２に対応する命令表の例を示す図である。
【図９】アドレスの特徴としてそのアドレスの法４に関する剰余を用いる場合の、剰余３に対応する命令表の例を示す図である。
【図１０】保護済みプログラムの具体例である。
【図１１】図１０の保護済みプログラムが実行される時点でのレジスタ部の状態を示す図である。
【図１２】プログラム実行装置をＶＭ（仮想マシン）として構成する場合の、プログラム実行装置による保護済みプログラムの処理手順の例を示す図である。
【図１３】ネイティブコードから保護済みプログラムの関数を呼び出す時点での、ＶＭを実行するネイティブ環境のスタック（実スタック）及びレジスタ（実レジスタ）の状態を示す図である。
【図１４】ＶＭの初期化処理の処理手順の例を示す図である。
【図１５】初期化処理実行後の実スタック及び実レジスタの状態を示す図である。
【図１６】ＶＭの終了処理の処理手順の例を示す図である。
【図１７】ＶＭの終了処理の開始時点での実スタック及び実レジスタの状態を示す図である。
【図１８】ＶＭの終了処理の完了時点での実スタック及び実レジスタの状態を示す図である。
【図１９】ＶＭを実現するエミュレータプログラムと保護済みプログラムとをひとまとまりにまとめたプログラムの構造の例を示す図である。
【図２０】各命令についてすべてのアドレス特徴（例えばアドレスの剰余）に対応するオペコードを示した命令表の例を示す図である。
【発明を実施するための形態】
【００１９】
図１〜図３を参照して、本実施形態におけるプログラムの難読化の仕組みを説明する。難読化とは、プログラムの解読を困難にすること、又はそのための処理のことを言う。
【００２０】
従来の機械語プログラムでは、命令は基本的に機械語のオペコード（命令コード）により表され、どのアドレスに置かれてもオペコードが表す意味（すなわちそのオペコードが表す演算処理）は変わらない。
【００２１】
これに対し、本実施形態では、オペコードが表す意味を、機械語プログラム中でそのオペコードが置かれるアドレスに依存させる。より詳しくは、オペコードの意味、すなわちそのオペコードを読み出したときに実行すべき演算処理を、そのオペコードと、そのオペコードを読み出したアドレスが持つ特徴と、の両方に基づいて決める。
【００２２】
ここでいう「アドレスが持つ特徴」（以下「アドレス特徴」とも呼ぶ）とは、そのアドレスの値、例えば３２ビット幅のアドレスであればそのアドレスの３２ビットの値、が示す特徴である。アドレス特徴としては、１つのアドレスから一意に定まるものを用いる。
【００２３】
例えば、そのアドレスをあらかじめ定めた法ｎ（ｎは自然数）で除したときの剰余を、そのアドレスの持つ「特徴」として用いる。もちろんこれは一例に過ぎない。アドレスのうち「１」であるビットの数、このようにアドレスに対してあらかじめ定めた処理を加えることで求められる別の数値を特徴として用いてもよい。ただし、アドレス特徴としては、その「特徴」を満たすアドレスを計算することが困難であるもの（例えばアドレスの暗号学的ハッシュ値）は用いない。
【００２４】
このようにオペコードの意味をアドレスに依存させた場合、例えば同じオペコードであってもそれが置かれるアドレスによって意味が変わる。本実施形態の方式で難読化されたプログラムは、アドレスを考慮に入れないとオペコードの意味が定まらないため（例えばオペコードの意味がアドレスによって変化するため）、解読が困難になる。
【００２５】
図１は、本実施形態におけるプログラムの難読化、及び難読化したプログラムの実行のための全体システムの例を示す。
【００２６】
このシステムは、原プログラム１４を難読化して保護するプログラム保護装置１２と、その難読化処理により保護されたプログラムである保護済みプログラム１６を実行するプログラム実行装置１８とを含む。
【００２７】
ここで、原プログラム１４は、難読化による保護が行われる前のプログラムである。原プログラム１４は、高級言語で記述されたソースコードであってもよいし、ソースコードをコンパイルしたオブジェクトコードであってもよい。ここでいうオブジェクトコードは、機械語で表現されたものであってもよいし、アセンブリ言語その他の中間言語で表現されたものでもよい。
【００２８】
一方、保護済みプログラム１６は、原プログラム１４に対して本実施形態の「アドレス依存」による難読化の処理を施すことで得られるプログラムであり、その保護済みプログラム１６が実行されるコンピュータが処理可能な機械語で表現される。
【００２９】
プログラム保護装置１２は、コンパイラ又はリンカ（リンケージエディタ）として実現すればよい。原プログラム１４を実行形式に変換する際に別のプログラム（例えばライブラリ）とリンクする必要がある場合、各命令のアドレスを最終的に決定するリンカに、プログラム保護装置１２の機能を持たせればよい。コンパイラが実行形式における各命令のアドレスを決定することができる場合は、プログラム保護装置１２の役割をコンパイラに持たせればよい。
【００３０】
図１の例では、原プログラム１４中の命令と、保護済みプログラム１６でその命令と同じ意味を表すオペコードとアドレス特徴の組合せと、の対応関係を規定する命令表１０を用いる。図１に示す命令表１０の例では、原プログラム１４中で「add」（加算）という名前で表される命令は、保護済みプログラム１６中では、オペコード「0」を、「特徴Ａ」を持つアドレスに配置することにより表現される。この命令表１０では、原プログラム１４中の「add」、「sub」（減算）、「and」（論理和）という名前の命令は、保護済みプログラム１６中ではすべて同じオペコード「0」で表現されるが、そのオペコードが置かれるアドレスが持つべき特徴は、それら命令毎に異なっている。
【００３１】
プログラム保護装置１２はこの命令表１０を参照して、原プログラム１４の命令を保護済みプログラム１６内でのオペコードとそのオペコードを配置するアドレスとを決定し、保護済みプログラム１６中のそのアドレスにそのオペコードを配置する。このようにして作成された保護済みプログラム１６内の各オペコードは、そのオペコード自身とそのオペコードの置かれたアドレスとの組合せに対応する意味を持っている。プログラム実行装置１８は、保護済みプログラム１６を実行する際、命令表１０を参照することで、読み出したオペコードの意味を特定し、その意味に応じた演算処理を実行する。
【００３２】
図２にプログラム保護装置１２の処理手順の例を示す。この手順では、プログラム保護装置１２は、原プログラム１４の先頭から順に１つずつ命令を取り出す（Ｓ１１）。次に、その命令の意味（すなわちその命令が指し示す演算処理）を表現する、保護済みプログラム１６中でのオペコードと、そのオペコードのアドレスとの組合せを、命令表１０に従って決定する（Ｓ１３）。通常、原プログラム１４中の命令を機械語に変換する場合、その命令に対応する機械語の命令は、その命令の実行順に従って先頭アドレスから順に配置されていく。これに対し、Ｓ１３では、そのような通常の変換処理（コンパイルやリンク）により定められる機械語命令のアドレス以降の、原プログラム１４中の命令に対応するアドレス特徴を持つアドレス（好適にはその特徴を持つアドレスのうち通常の変換処理で定められるアドレスに最も近いもの）を、その命令に対応するオペコードの配置先に決定する。
【００３３】
Ｓ１３で決定したオペコードの配置先アドレスが、通常の変換処理で定められるアドレスと異なっている場合、既に配置済みの命令群とＳ１３で決定した今回の命令の配置先のアドレスとの間に隙間ができる。このような隙間ができる場合には、プログラム保護装置１２は、その隙間をnop（no operation：「何もしない」ことを意味する）命令で埋めたり、配置済みの命令の最後の命令の直後に、Ｓ１３で決定したアドレスにジャンプすることを指示するジャンプ命令を追加したりする（Ｓ１５）。これにより、今回配置する命令が、既に配置済みの最後の命令の後の最初の意味のある命令（実質的な演算操作）となる。
【００３４】
またプログラム保護装置１２は、Ｓ１３で求めたオペコードを、保護済みプログラム１６中のＳ１３で求めたアドレスに配置し、そのオペコードの後に、必要なオペランドを配置する（Ｓ１７）。
【００３５】
そして、プログラム保護装置１２は、原プログラム１４の最後まで変換が完了したかどうかを判定し（Ｓ１９）、最後まで完了していれば変換処理を終了し、最後まで完了していなければ、Ｓ１１に戻る。
【００３６】
次に、図３を参照して、プログラム実行装置１８が保護済みプログラム１６を実行する際の処理手順の例を説明する。
【００３７】
プログラム実行装置１８は、保護済みプログラム１６の先頭アドレスから順にオペコードを読み込む（Ｓ２１）。次に、読み込んだオペコードと、そのオペコードが置かれていたアドレス（これはプログラムカウンタ、インストラクションポインタ等が示している）の特徴との組合せに対応する操作の意味（すなわち、原プログラム１４中での命令の意味）を、命令表１０から求める（Ｓ２３）。より詳しくは、そのオペコードが置かれていたアドレスの値から、そのアドレスの特徴を求め、その特徴とそのオペコードとの組合せに対応する命令を命令表１０から求める。そして、命令表１０に示されるその命令のオペランド形式の情報（図示省略）に従い、保護済みプログラム１６中のそのオペコードの後に続くオペランドを読み出し、Ｓ２３で判定したオペコードが示す演算操作を、読み出したオペランドに対して実行する（Ｓ２５）。また、次に実行するオペコードのアドレスを示すポインタ（プログラムカウンタ）の値を、それらオペコードとオペランドのバイト数だけ増加させる（Ｓ２７）。そして、保護済みプログラム１６の最後まで実行し終わったか否かを判定し（Ｓ２９）、終わっていれば処理を終了し、終わっていなければＳ２１に戻って次のオペコードを読み出す。
【００３８】
以上に説明した実施形態のシステムでは、保護済みプログラム１６は、通常の暗号化アルゴリズムによる暗号化は施されていないが、その代わりにオペコードの意味をそのオペコードのアドレスに依存させることで、解読され難くなっている。なお、本実施形態のアドレス依存による難読化を施した後に、暗号化アルゴリズムによる暗号化を施してももちろんよい。
【００３９】
次に、本実施形態の方式のより具体的な実施例を説明する。
【００４０】
図４は、この実施例におけるプログラム実行装置１８の機能構成の一例を示す図である。プログラム実行装置１８は、ハードウエアのプロセッサとメモリを含む物理的なコンピュータとして実装してもよいし、物理的なコンピュータ上で実行される仮想マシン（ＶＭ）として実装してもよい。
【００４１】
図４において、メモリ１００には、保護済みプログラム１６がロードされていると共に、保護済みプログラム１６の実行の際に用いられるデータやスタックの領域が確保されている。図では、わかりやすさのために保護済みプログラム１６の各命令のオペコードやオペランドをニーモニックで表現しているが、実際には機械語のコードである。プログラム実行装置１８をＶＭとして実装する場合は、メモリ１００はそのＶＭが用いるメモリ空間である。
【００４２】
命令表１〜Ｎ（図では符号１４０−１〜１４０−Ｎで示す）は、オペコードが置かれたアドレスが持つアドレス特徴毎に個別に用意された命令表である。図１の例では、すべてのアドレス特徴についての情報が１つの命令表１０にまとめられていたが、図３の例では、「アドレス特徴１には命令表１」、「アドレス特徴２」には命令表２というように、アドレス特徴毎に命令表１〜Ｎが分けられている。このような分割形式の命令表については、後で図６〜図９を参照しながら具体的な例を説明する。プログラム実行装置１８を物理的なコンピュータとして実装する場合、命令表１〜Ｎは、ＲＯＭ（リードオンリーメモリ）に保持させてもよいし、メインメモリ上にロードして利用するようにしてもよい。
【００４３】
レジスタ部１６０は、プログラムの実行途中の処理の状態を保持する。プログラム実行装置１８を物理的なコンピュータとして実装する場合、レジスタ部１６０は、ＣＰＵに内蔵されるレジスタに相当する。レジスタ部１６０は、演算結果やデータを一時的に記憶する汎用レジスタ（図の符号ｒ０、ｒ１，・・・）、スタックの先頭（スタックトップ）のアドレスを保持するレジスタ（ｓｐ：スタックポインタ）、次に実行すべき命令のアドレスを保持するレジスタ（ｉｐ：インストラクションポインタ）等を含んでいる。
【００４４】
命令読込部１２０は、レジスタｉｐが示すアドレスから、次に実行すべき命令を読み込む。命令は、基本的にはオペコードとオペランドとを含む。以下の例では、オペコード毎に、オペランドの数やデータ幅が個別に定まっているものとする。またオペランドのないオペコードも存在する。
【００４５】
アドレス特徴判定部１３０は、レジスタｉｐが示すアドレスの値からそのアドレスの特徴を求める。例えば、アドレスの特徴として、法ｎに関する剰余を用いる場合は、アドレス特徴判定部１３０は、アドレスの値をｎで除算したときの剰余を計算する。
【００４６】
処理実行部１１０は、実行形式のプログラムを実行する演算部であり、この例では保護済みプログラム１６を実行する機能を有する。処理実行部１１０は、命令読込部１２０が読み込んだ命令の内容に応じ、必要な場合にはレジスタ部１６０や（読み書き部１７０を介して）メモリ１００からデータを読み込み、そのデータを用いてその命令の示す処理を実行する。また、その処理に応じてレジスタ部１６０内の各レジスタの値を更新したり、処理結果のデータを、読み書き部１７０を介してメモリ１００に書き込んだりする。処理実行部１１０は、レジスタｉｐの値を、ジャンプ命令を実行した場合にはそのジャンプ命令が示すジャンプ先のアドレスへと変更する。また、他の命令を実行した場合にはその命令の大きさ（オペコード及びオペランドのデータ量の合計）に対応する値だけレジスタｉｐの値を増やす。
【００４７】
また、処理実行部１１０は、保護済みプログラム１６の実行の際に、アドレス特徴判定部１３０が判定したアドレス特徴に対応する命令表（１〜Ｎのいずれか）を参照することで、実行すべき命令の意味（すなわち演算処理の種類）を判定する。
【００４８】
プログラム実行装置１８を物理的なコンピュータとして実装する場合、処理実行部１１０はＣＰＵ（中央演算装置）に相当するが、一般的なＣＰＵと異なり、命令表１〜Ｎを参照することで、オペコードに対応する演算処理を特定する機能を有している。
【００４９】
次に、図５〜図９を参照して、分割形式の命令表１〜Ｎの具体例を説明する。
【００５０】
図５は、この実施例のプログラム実行装置１８が用いる命令形式を示す。図５に示した命令形式は、ＭＩＰＳアーキテクチャの命令形式に似たものであり、Ｒ、Ｉ、Ｊ、及びＯの各命令形式を含む。例えばＲ形式の命令は、８ビットのオペコードの後に、オペランドとしてｓ、ｔ、及びｄの３つのレジスタを指し示すそれぞれ８ビットのアドレスが続く、合計４バイトの命令である。
【００５１】
図６〜図８は、アドレス特徴として、アドレスの法４に関する剰余を用いた場合の４つの命令表０〜４の例を示している。図６は剰余が「０」の場合に用いる命令表１を示し、図７〜図９は、剰余が「１」〜「３」の場合に用いる命令表２〜４をそれぞれ示す。
【００５２】
命令表の個々の項目の意味を、図６の命令表１を例にとって説明する。命令表１が示すところでは、例えば原プログラム１４中の「add」（加算）という名称の命令は、原プログラム１４中では「add $d, $s, $t」という構文をとり、その構文の意味は「$d = $s + $t」（レジスタsの値とレジスタtの値との加算結果をレジスタdに書き込む）であり、この命令に対応する機械語の命令形式がＲ形式であり、機械語のオペコードが１６進数で「0」である。また、原プログラム１４中の命令「Load double word」は、「ld $t, C($s)」という構文をとり、その構文の意味は「$t = Memory[$s + C]  (4byteデータ)」（レジスタsに格納された値に即値Cを加算した値であるアドレスから、４バイトの連続する位置にあるデータをロードし、レジスタtに格納する）であり、この命令に対応する機械語の命令形式がＩ形式であり、機械語のオペコードが１６進数で「0x33」である。
【００５３】
図６〜図９を比較すれば分かるように、命令表１〜４には同じオペコードが含まれている。例えば、オペコード「0」は、命令表１では命令「add」を、命令表２では命令「subtract」、命令表３では命令「and」を、命令表４では命令「or」を、それぞれ意味する。すなわち、保護済みプログラム１６中のオペコード「0」は、そのオペコード「0」が置かれているアドレスの法４に関する剰余が「０」であれば命令「add」を、「１」であれば命令「subtract」を、「２」であれば命令「and」を、「３」であれば命令「or」を、それぞれ意味する。
【００５４】
１つの剰余に対応する１つの命令表内では、原プログラム１４中の命令（項目「名称」によって示される）と保護済みプログラム１６中のオペコードとは一対一に対応している。
【００５５】
また、基本的には、１つの命令は１つの命令表のみに含まれており、同じ命令が複数の命令表に登場することはない。ただし、本実施形態の難読化方法のために追加が必要なジャンプ命令（名称「jump」）又はnop命令については、すべての命令表１〜４に含まれる。
【００５６】
図６〜図９に示す命令表の例では、アドレス特徴として法４に関する剰余を用いたが、これにはいくつかの利点がある。まず、オペレーティングシステムのメモリ管理では、例えば４ｋバイト（４０９６バイト）や２ｋバイトなどといった、２のべき乗バイトのサイズのページを単位としてプログラムやデータが物理メモリにマッピングされる（ページング）。アドレスの法４に関する剰余はページングによっては変化しないので、どこのページにページインされるかに応じて剰余の計算に調整を加える等の手間がかからない。また、法４の剰余は、アドレスの上位ビットをマスクして下位２ビットを取り出すという簡単な演算で求めることができる。これら利点は、４を法とする場合だけでなく、２のべき乗である他の値（例えば２、８、１６など）を法とした場合のアドレスの剰余をアドレス特徴として用いる場合にも得られる。
【００５７】
次に、処理実行部１１０が、図１０に示す具体的な保護済みプログラム１６の命令列を、図６〜図９の命令表１〜４を参照しながら実行する処理の流れを説明する。
【００５８】
図１０に示す命令列は、メモリ１００のアドレス0x100から始まっている。また、メモリ１００上のデータはリトルエンディアンで表現されている。
【００５９】
この例では、処理実行部１１０が演算処理に用いるレジスタ群には、図１１に示すようにレジスタ番号０〜３の４つの汎用レジスタｒ０〜ｒ３と、レジスタ番号４で参照されるスタックポインタｓｐと、次に実行する命令のアドレスを示すインストラクションポインタｉｐ等が含まれる。図１１は、アドレス0x100の命令を実行する直前でのレジスタ群の状態を示しており、このときｉｐが保持する次の命令のアドレスは0x100であり、ｓｐが保持するスタックトップのアドレスは0x400であるとする。
【００６０】
処理実行部１１０は、まずｉｐの持つ値が0x100なので、メモリ１００上のアドレス0x100から命令を読み込む。また、アドレス特徴判定部１３０が、そのアドレス0x100の法４に関する剰余をアドレス特徴として計算する。この場合剰余は０となり、この剰余０を処理実行部１１０に通知する。これに応じ、処理実行部１１０は、剰余０に対応する命令表１（図６）を選択する。この命令表１から、処理実行部１１０は、アドレス0x100から始まる命令の先頭バイトであるオペコード0x33が、Ｉ形式で、オペランドを含めて７バイト長の、Load double word命令を示すものであると認識する。また、この命令はＩ形式（図５参照）であるから、２バイト目は$sレジスタを、３バイト目は$tレジスタを、４〜７バイト目が３２ビットの即値であるオフセットCを示す。したがって、処理実行部１１０は、２バイト目の値が0x04であるからアドレス0x04で示されるスタックポインタｓｐ（保持する値は0x400）を$sレジスタとし、３バイト目の値が0x0であるからアドレス0x0で示される汎用レジスタｒ０を$tレジスタとする。また、４〜７バイト目をリトルエンディアンで読んだ値0x108がオフセットCである。したがって、処理実行部１１０は、メモリ１００上の、スタックポインタｓｐの値0x400にオフセット0x108を加えたアドレス0x508から始まる、リトルエンディアンで示される４バイトの値を、レジスタｒ０に読み込む。そして、今７バイト長の命令を実行したので、インストラクションポインタｉｐを、７だけ増やして0x107とする。
【００６１】
次に処理実行部１１０は、ｉｐが示すアドレス0x107から次の命令を読み込む。また、アドレス特徴判定部１３０は、そのアドレス0x107の法４に関する剰余を求め、その剰余の値１を処理実行部１１０に渡す。これに応じて処理実行部１１０は、剰余１に対応する命令表２（図７）を選択する。そして、この命令表２から、メモリ１００上のアドレス0x107の値すなわちこの命令のオペコード0xfcが、Ｏ形式で、このオペコードを含めて１バイト長のnop命令であると判断する。したがって、処理実行部１１０は、何も行わず（nop命令）、当該オペコードの下位２ビットが０であることから、ｉｐに１＋０の結果である１を加え、0x108とする。
【００６２】
次に処理実行部１１０は、ｉｐが示すアドレス0x108から次の命令を読み込む。また、アドレス特徴判定部１３０は、そのアドレス0x108の法４に関する剰余を求め、その剰余の値０を処理実行部１１０に渡す。これに応じて処理実行部１１０は、剰余０に対応する命令表１（図６）を選択する。そして、この命令表１から、メモリ１００上のアドレス0x108の値すなわちこの命令のオペコード0x33が、Ｉ形式で、７バイト長のLoad double word命令であると判断する。したがって、処理実行部１１０は、既に説明したアドレス0x100の命令の場合と同様、スタックポインタｓｐの値0x400に即値オフセット0x10cを加算してアドレス0x50cを求め、メモリ１００上のこのアドレス0x50cから始まる４バイトの値を、アドレス0x01が示す汎用レジスタｒ１に読み込む。そしてｉｐの値を７だけ増やして0x10fとする。
【００６３】
次に、ｉｐが示すアドレス0x10fの法４に関する剰余は３なので命令表４（図９）を用いる。メモリ１００上のアドレス0x10fから始まる命令の先頭のオペコード0xfdは命令表４からnop命令であることが分かるので、処理実行部１１０は、演算処理は行わず、ｉｐの値を、そのオペコード0xfdの下位２ビットの値１に応じて１＋１、すなわち２だけ増やす。したがって、ｉｐの値は0x111となる。
【００６４】
次にｉｐが示すアドレス0x111の法４に関する剰余は１なので命令表２（図７）を用いる。メモリ１００上のアドレス0x111から始まる命令の先頭すなわちオペコードは0x0であり、命令表４からこのオペコードがＲ形式で、４バイト長のsubtract命令であることが分かる。この命令はＲ形式（図５参照）であるから、２バイト目は$sレジスタを、３バイト目は$tレジスタを、４バイト目は$dレジスタを示す。したがって、処理実行部１１０は、２バイト目の値0x01が示すレジスタｒ１の値から、３バイト目の値0x0が示すレジスタｒ０の値を減算し、その減算結果を４バイト目の値0x03が示すレジスタｒ３に格納する。プログラム実行装置１８をＶＭ（仮想マシン）として構成した場合、ＶＭの仕様によっては、この演算の際にフラグレジスタの値が設定されることがあるが、この点は本発明とは直接関係しないので説明は省略する。４バイト長の命令を実行したので、ｉｐの値に４が加算され、0x115となる。
【００６５】
次に、ｉｐが示すアドレス0x115の法４に関する剰余は１なので命令表２（図７）を用いる。メモリ１００上のアドレス0x115から始まる命令の先頭のオペコード0xf0は命令表２からＪ形式のjump命令であることが分かり、更にＪ形式の定義（図５参照）も合わせるとその命令の２〜５バイト目の３２ビットの値がアドレスのジャンプ量Cを示すことが分かる。そこで処理実行部１１０は、ｉｐの値0x115にジャンプ量0x0dを加算する。これによりｉｐの値が0x121となる。
【００６６】
次にｉｐが示すアドレス0x121の法４に関する剰余は１なので命令表２（図７）を用いる。メモリ１００上のアドレス0x121から始まる命令の先頭すなわちオペコードは0x33であり、命令表２からこのオペコードがＩ形式で、７バイト長のstore double word命令であることが分かる。この命令はＩ形式（図５参照）であるから、２バイト目は$sレジスタを、３バイト目は$tレジスタを、４〜７バイト目は即値のオフセットCを示す。したがって、処理実行部１１０は、２バイト目の値0x04が示すスタックポインタｓｐの値0x400に対して４〜７バイト目が示す値0x110を加算して得られるメモリ１００上のアドレス0x510に対し、３バイト目の値0x3が示すレジスタｒ３が持つ値を、リトルエンディアン４バイトの値として書き込む。今７バイト長の命令を実行したので、ｉｐの値は７増えて0x128となる。
【００６７】
このように、処理実行部１１０は、実行する命令の先頭アドレス（ｉｐが指し示している）の、法４に関する剰余に応じて、命令の意味の判定に使用する命令表を切り換えている。
【００６８】
次に、図１２を参照して、プログラム実行装置１８をＶＭとして実現した場合の処理手順の例を説明する。
【００６９】
図１２に示す手順では、プログラム実行装置１８（ＶＭとして実現される）を表すプログラムを実行するコンピュータが、ＶＭの準備を行う（Ｓ１００）。このＳ１００では、一般的なプロセス構築と同様の処理でＶＭのプロセスを構築する。
【００７０】
次に、構築されたＶＭすなわちプログラム実行装置１８が、メモリ１００上のインストラクションポインタｉｐの示すアドレスから、保護済みプログラム１６の命令を１つ読み込む（Ｓ１２０）と共に、ｉｐの示すアドレスの示す特徴（例えば法ｎに関する剰余）を判定する（Ｓ１２２）。次にプログラム実行装置１８は、判定したアドレス特徴に対応する命令表１４０（図４参照）を選択し（Ｓ１２４）、読み込んだ命令のオペコードが表す演算処理の内容を、Ｓ１０６で選択した命令表１４０から特定する（Ｓ１２６）。それから、（そのオペコードに続くオペランド（もしあれば）に対して）特定した演算処理を実行し（Ｓ１２８）、その命令の大きさだけｉｐの値を増やす（Ｓ１３０）。そして、保護済みプログラム１６の最後の命令まで処理し終えたかどうかを判定し（Ｓ１３２）、処理し終えていなければＳ１０２に戻って、ｉｐが示す次の命令の処理を行う。処理し終えていれば、ＶＭの終了処理を実行する（Ｓ１４０）。このＳ１３２の処理は、プロセスの終了命令に達したかを判定する一般的な終了判定処理でよいし、ＶＭ終了処理（Ｓ１４０）は、一般的なプロセス終了処理でよい。
【００７１】
プログラム実行装置１８を物理的なコンピュータとして実現する場合、図１２のＳ１００の準備処理は、保護済みプログラム１６を実行するプロセスを構築する処理となり、この処理は従来の一般的なプロセス構築処理と同様でよい。その後に続くＳ１２０からＳ１３０の処理も、上で説明したのと同様でよい。また、保護済みプログラム１６を最後まで処理し終えたかどうかを判定する処理（Ｓ１３２）は、プロセスの終了命令に達したかを判定する一般的な終了判定処理でよいし、保護済みプログラム１６の実行終了処理（Ｓ１４０）は、一般的なプロセス終了処理でよい。
【００７２】
また、変形例として、特開２０１３−２００８３１号公報に示した処理方式を用い、ネイティブ環境のＣＰＵが実行するネイティブコードから、保護済みプログラム１６を関数単位で呼び出してＶＭ上で実行することも可能である。
【００７３】
この例では、ネイティブコードから保護済みプログラム１６の関数を呼び出す度に、図１２の処理が実行されることとなる。
【００７４】
この呼び出しの時点での、ＶＭを実行するネイティブ環境のスタック（実スタック）及びレジスタ（実レジスタ）の内容が図１３で示すものであるとする。図１３の例では、保護済みプログラム１６の関数を４つの引数（引数１，２，３，４と呼ぶ）と共に呼び出している。この時点では、実スタックの先頭（トップ）には、呼び出し元への戻りアドレスの値が置かれ、その次に引数３及び引数４がこの順に置かれている。また、この時点では、ネイティブ環境（実ＣＰＵ）が使用している実レジスタ群の中の、あらかじめ定められたスタックポインタ用のレジスタｓｐには上述の戻りアドレスが置かれたスタック位置を示すアドレス値が置かれている。また、番号０のレジスタｒ０には引数１が、番号１のレジスタｒ１には引数２が、それぞれに置かれている。インストラクションポインタｉｐは、ネイティブコード中において保護対象関数の代わりに置かれているラップコード（詳細は特開２０１３−２００８３１号公報を参照）の先頭を示しているがここでは重要でないため図示していない。
【００７５】
また、この例では、図１２のＳ１００の処理は、例えば図１４に示すものとなる。この手順では、まず、実スタックの未使用領域に、ＶＭで用いるメモリ領域、すなわち、レジスタ部１６０とメモリ１００（保護済みプログラム１６とデータを記憶する領域、スタック領域を含む）を確保する（Ｓ１０２）。これに伴い、実レジスタのスタックポインタｓｐの値を、このとき確保した領域サイズの分だけ減算する。次に、破壊してはいけないレジスタの値を、Ｓ１０２で確保したメモリ領域の中に複写して保存する（Ｓ１０４）。ここで、ＶＭの処理に必要なレジスタがあればその値を設定する（Ｓ１０６）。その後、ＶＭで実行する保護済みプログラムの関数に渡された引数を複写する（Ｓ１０８）。ここでは、ネイティブ環境のＣＰＵで使われているアプリケーションバイナリインタフェース（ＡＢＩ）とＶＭで使われているＡＢＩとの間で対応がとられた場所（レジスタ又はスタック）に複写する必要がある。次にＶＭのレジスタであるレジスタ部１６０のインストラクションポインタｉｐの値を、最初にＶＭで実行する命令が格納されたアドレスに設定する（Ｓ１１０）。そして最後に、レジスタ部１６０のスタックポインタｓｐの値を、ＶＭで使用するスタックのVM開始時の先頭アドレス（すなわちＶＭ環境のために確保したスタックの先頭アドレス）に設定する（Ｓ１１２）。
【００７６】
以上に説明した図１４の処理の結果、実スタック及び実レジスタの状態は図１５に示す状態となり、これによりＶＭ上でプログラム実行装置１８の処理を開始できる状態になる。この後、図１２のＳ１２０〜Ｓ１３２の処理を実行する。ここで、このネイティブコードから関数単位で保護済みプログラム１６を呼び出す変形例では、Ｓ１３２の終了判定では、実行する命令が関数からの戻り命令であるかどうかを判定すればよい。すなわち、戻り命令であれば終了に達したと判定してＳ１４０に進み、そうでなければＳ１２０に戻るようにすればよい。
【００７７】
この変形例では、次のＳ１４０のＶＭ終了処理は、図１６に示す手順となる。図１７に、この処理の開始時点での実スタック及び実レジスタの状態を示す。
【００７８】
図１６の処理では、まず、ＶＭ上で実行した関数からの戻り値を、呼び出し元である実ＣＰＵから呼び出された関数呼び出しの戻り値の場所（レジスタ又はスタックのうち実ＣＰＵのＡＢＩに応じた方）へ複写する（Ｓ１４２）。次に、Ｓ１０４（図１４参照）で退避したレジスタの値を、もとのレジスタに戻す（Ｓ１４４）。また、Ｓ１０２で確保した領域を解放する（Ｓ１４６）。この結果、実ＣＰＵのスタックポインタｓｐがＳ１０２開始時のｓｐの値に戻る。そして、実ＣＰＵが、関数からの戻り命令を実行し、処理を呼び出し元へ戻す（ｓ１４８）。以上の結果、実スタック及び実レジスタの状態は、図１８に示す状態となり、実ＣＰＵが呼び出し元のネイティブコードの処理を継続することが可能になる。
【００７９】
以上図１２〜図１６を参照して説明した変形例の処理の詳細については、特開２０１３−２００８３１号公報に開示された処理内容も参照されたい。
【００８０】
以上では、プログラム実行装置１８をネイティブ環境（実ＣＰＵ、実メモリ、オペレーティングシステム等からなる）上でエミュレートされるＶＭとして実現する例をいくつか説明した。このようなＶＭを実現するエミュレータプログラムと、保護済みプログラム１６と、をひとまとまりのプログラムにまとめてもよい。このようにまとめた実行形式のプログラムの例を図１９に模式的に示す。
【００８１】
図１９のプログラムは、ヘッダの後のコード領域に本実施形態の保護方式の対象外のプログラムコード（「保護対象外コード」）が続く。そして、その後に、ＶＭの初期化処理（図１２のＳ１００。図１４）を行うＶＭ初期化部、処理実行部１１０、命令読込部１２０、及びアドレス特徴判定部１３０のプログラムコード、各命令表１４０、並びに、ＶＭの終了処理（図１２のＳ１４０。図１６）を行うＶＭ終了部のプログラムコードが続く。そして、その後のデータ領域内に、本実施形態のアドレス依存による保護を加えた保護済みプログラム１６が含まれる。
【００８２】
プログラム保護装置１２は、保護済みプログラム１６を含む図１９に示した構造のプログラムを生成してもよい。この構造のプログラムが、ユーザに対して配布される。
【００８３】
ユーザがコンピュータにて図１９に例示した構造を有するプログラムを実行することで、必要な初期化処理の後に、そのコンピュータのネイティブ環境上でＶＭがエミュレートされる。ＶＭを構成する処理実行部１１０、命令読込部１２０、及びアドレス特徴判定部１３０が命令表１４０を参照しつつ上述の動作を行うことで、保護済みプログラム１６がＶＭ上で実行される。保護済みプログラム１６の実行のあと、ＶＭ終了部の実行により、ネイティブ環境に制御が戻される。
【００８４】
さて、図１０に例示した保護済みプログラム１６を作成するプログラム保護装置１２の処理手順は、大略的には図２を用いて既に説明したとおりである。
【００８５】
ここで、図２の手順では、Ｓ１３で決定したオペコードの配置先アドレスが通常の変換処理で定められるアドレスと異なっている場合に生じる隙間を埋めるために、nop命令やジャンプ命令を挿入した。
【００８６】
一方、プログラム保護装置１２のベースとなるコンパイラやリンカは、一般にコードサイズをできるだけ小さくするような最適化機能を備える。
【００８７】
そこで、本実施形態では、この最適化機能を改良して、配置する命令（オペコード、及びもしあればオペランド）の並びを、演算処理の内容を変化させない範囲で並べ替えることで、nop命令やジャンプ命令の挿入をできるだけ少なくするようにしてもよい。例えば、Ｓ１３で、既に命令配置済みの部分と今回配置するオペコードのアドレスとの間に隙間ができることが分かった場合、後続の命令の中でその隙間内に配置しても演算処理を変化させないものを探し、そのようなものが見つかれば、その命令を隙間内に配置する。ここで、その後続の命令のその隙間内での配置先アドレスは、命令表１〜４に規定されるアドレス特徴の制約を満たすよう、Ｓ１３と同様の処理により求める必要がある。また、その後続の命令に対応するオペコードをそのアドレス制約を満たす隙間内のアドレスに配置したときに、その命令のオペランドがすべてその隙間内に配置できる必要がある。このような条件を満たすよう、命令の並び順の入れ替えが可能かどうか判定する。
【００８８】
上述の実施形態で用いた図６〜図９に示した命令表は、同じオペコードを、そのオペコードが置かれるアドレスの特徴（例えば法４に関する剰余）毎に異なる意味（演算処理内容）で用いるものであった。また、原プログラム１４の１つの命令は１つの命令表に含まれるのみであった。このため、原プログラム１４のある意味の命令を示す保護済みプログラム１６のオペコードは、その意味に対応するアドレス特徴を持つアドレスに配置しなければならないという制約があり、この制約を満たすため、nop命令やジャンプ命令を追加する必要があった。
【００８９】
これに対し、更なる変形例として、そのようなオペコードの配置先アドレスの制約をなくすことも可能である。この変形例では、原プログラム１４の個々の命令に対して、アドレス特徴毎にそれぞれ別々のオペコードを割り当てる。ただし、あるアドレスから読み出した１つのオペコードに複数の解釈が生じないよう、異なる２以上の命令について、同じアドレス特徴に対応するオペコードが同じ値とならないようにする。
【００９０】
図２０に、この変形例で用いる命令表の一例を示す。この命令表は、アドレスの法４についての剰余をアドレス特徴として用いる場合の例であり、４つのアドレス特徴（剰余０〜３）についてのオペコード群を１つの表にまとめたものである。この命令表では、例えば、命令addについて、アドレスの剰余が０の場合のオペコードは0x0、剰余が１の場合のオペコードは0x12、剰余が２の場合のオペコードは0xc9、剰余が３の場合のオペコードは0x72と規定されている。また、命令addの剰余０に対応するオペコードと、命令Load double wordの剰余２に対応するオペコードとは共に0x0となっているように、異なるアドレス特徴同士の間では、同じオペコードが用いられている。しかし、上述の通り、同じ剰余の中では、命令が異なれば、オペコードも異なる。
【００９１】
この命令表を用いる場合、プログラム実行装置１８は、保護済みプログラム１６から読み出したオペコードの置かれていたアドレスの法４に関する剰余を求め、その剰余とそのオペコードの組合せに対応する命令の演算処理内容を命令表から特定し、実行すればよい。
【００９２】
また、プログラム保護装置１２は、原プログラム１４内の命令をオペコードに変換して配置する際、その配置先のアドレス（これは通常のコンパイラ、リンカの処理において決定される配置先のアドレスである）のアドレス特徴（法４に関する剰余）を求め、その命令とそのアドレス特徴の組に対応するオペコードを図２０の命令表から求め、求めた命令表をそのアドレスに配置すればよい。
【００９３】
このように、図２０に例示した、１つの命令について、すべてのアドレス特徴に対応するオペコードを規定した命令表を用いる場合には、通常のコンパイラ、リンカの処理において決定される配置先のアドレスにオペコードを配置すればよく、図２の手順のＳ１５のような特別なnop命令やジャンプ命令の挿入処理は不要である。ただし、不要なnop命令やジャンプ命令をあえて挿入して命令のアドレスを変化させるようにしてもよい。
【００９４】
以上の実施形態及び変形例では、プログラム実行装置１８内の処理実行部１１０が、命令表１４０を参照しながらオペコードに対応する演算処理を求めた。しかしこのようなテーブル引きを行う構成はあくまで一例に過ぎない。別の例として、アドレスに依存するオペコードの演算内容を特定する機能を、処理実行部１１０に内蔵してもよい。
【００９５】
例えば、処理実行部１１０をＶＭ等のように、物理的なコンピュータ上で実行されるプログラムとして実現する場合、アドレス特徴を求める処理と、求めたアドレス特徴とオペコードとの組合せに対応する演算処理を特定して実行する処理と、をコンピュータに実行させるためのコードをそのプログラム中に含めればよい。１つの例として、アドレス特徴による条件分岐とオペコードによる条件分岐との二段階の条件分岐により、そのオペコードに応じて行う演算処理を特定するプログラムが考えられる。
【００９６】
一例として、オペコードに対応する演算処理を図６〜図９に例示した４つの命令表を参照して特定する処理を、Ｃ言語のswitch-case文に似た構文で示した擬似プログラムコードを以下に示す。
【００９７】
（数１）
switch(命令が置かれたアドレス%4) {
case 0; //命令表１を用いる場合に対応
switch(オペコード) {
case 0;
add命令の実行コード;
break;
case 0x33;
double wordのロード命令の実行コード;
break;
...
case 1; //命令表２を用いる場合に対応
switch(オペコード) {
case 0;
subtract命令の実行コード;
break;
case 0x33;
double wordのストア命令の実行コード;
break;
...
case 2; //命令表３を用いる場合に対応
switch(オペコード) {
case 0;
and命令の実行コード;
break;
...
case 3; //命令表４を用いる場合に対応
switch(オペコード) {
case 0;
or命令の実行コード;
break;
...
【００９８】
処理実行部１１０は、このようなプログラム部分を実行することで、オペコードと、そのオペコードが置かれたアドレスの特徴との組合せに対応する演算処理を実行する。例えば、読み出したオペコードが0x33であり、そのオペコードのアドレスの法４に関する剰余が０である場合、処理実行部１１０は２ワードのデータをロードするという演算処理を実行することとなる。
【００９９】
以上に例示したプログラム保護装置１２及びプログラム実行装置１８は、例えば、汎用のコンピュータに当該装置の各機能モジュールの処理を表すプログラムを実行させることにより実現してもよい。ここで言うコンピュータは、例えば、ハードウエアとして、ＣＰＵ等のマイクロプロセッサ、ランダムアクセスメモリ（ＲＡＭ）およびリードオンリメモリ（ＲＯＭ）等のメモリ（一次記憶）、ＨＤＤ（ハードディスクドライブ）やＳＳＤ（ソリッドステートドライブ）、フラッシュメモリ等の二次記憶を制御する二次記憶コントローラ、各種Ｉ／Ｏ（入出力）インタフェース、無線又は有線のネットワークとの接続のための制御を行うネットワークインタフェース等が、たとえばバスを介して接続された回路構成を有する。また、そのバスに対し、例えばＩ／Ｏインタフェース経由で、ＣＤやＤＶＤ、ブルーレイディスクなどの可搬型ディスク記録媒体に対する読み取り及び／又は書き込みのためのディスクドライブ、フラッシュメモリなどの各種規格の可搬型の不揮発性記録媒体に対する読み取り及び／又は書き込みのためのメモリリーダライタ、などが接続されてもよい。上に例示した各機能モジュールの処理内容が記述されたプログラムがＣＤやＤＶＤ等の記録媒体を経由して、又はネットワーク等の通信手段経由で、フラッシュメモリ等の二次記憶装置に保存され、コンピュータにインストールされる。二次記憶装置に記憶されたプログラムがＲＡＭに読み出されＣＰＵ等のマイクロプロセッサにより実行されることにより、上に例示した機能モジュール群が実現される。
【符号の説明】
【０１００】
１０  命令表、１２  プログラム保護装置、１４  原プログラム、１６  保護済みプログラム、１８  プログラム実行装置、１００  メモリ、１１０  処理実行部、１２０  命令読込部、１３０  アドレス特徴判定部、１４０  命令表、１６０  レジスタ部、１７０  読み書き部。
【図１】
2016057991.tif 000003
【図２】
2016057991.tif 000004
【図３】
2016057991.tif 000005
【図４】
2016057991.tif 000006
【図５】
2016057991.tif 000007
【図６】
2016057991.tif 000008
【図７】
2016057991.tif 000009
【図８】
2016057991.tif 000010
【図９】
2016057991.tif 000011
【図１０】
2016057991.tif 000012
【図１１】
2016057991.tif 000013
【図１２】
2016057991.tif 000014
【図１３】
2016057991.tif 000015
【図１４】
2016057991.tif 000016
【図１５】
2016057991.tif 000017
【図１６】
2016057991.tif 000018
【図１７】
2016057991.tif 000019
【図１８】
2016057991.tif 000020
【図１９】
2016057991.tif 000021
【図２０】
2016057991.tif 000022