インドリ 2008/10/28 14:00

 本稿では、VB.NETを利用し、簡単な機械語で動く仮想CPUを作ることでバイナリプログラミングを満喫します。実際の業務で直接使えるケースは少ないと思いますが、デバッグやプログラミングの地力向上に役立つでしょう。今回はMUL命令の実装を通じて、ソースオペランドにレジスタを指定する機械語の実装法を解説します。

1 2 3 4 5 →

はじめに

 本記事はVB.NETの初歩的な記法だけを使って、簡単な機械語で動く仮想CPUの実装法を解説します(※CPUにもいろいろありますが、この記事ではIntel社が製造しているCPUを対象とします)。その過程を通じて、初心者でもバイナリプログラミングが楽しめることと、バイナリプログラミングの魅力を伝えたいと思っています。

 今回はMULの実装を通じて、ソースオペランドにレジスタを指定する機械語の実装法を解説します。

これまでの連載

下準備

 今回は前回の実装を拡張していきますので、あらかじめ第9回までの部分の実装を済ませておいてください。

MUL命令の概要

 MUL命令は今まで実装した命令とは性質が異なりますので、まずはMUL命令の概要から解説します。今まで実装してきた算術命令は次の形式でした。

命令 ディスティネーションオペランド ソースオペランド

 今まで、ディスティネーションオペランドとソースオペランドを説明していなかったので、この機会に説明しておきます。ディスティネーション(destination)とは、目的地、届け先、行き先などの意を持つ英単語で、算術命令では結果を保存する場所を示しています。一方、ソース(source)とは、源、源泉、転送元などの意を持つ英単語で、算術命令では計算に使用する値(ADDの場合は加算値、SUBの場合は減算値)を示しています。

 あと、オペランドについてですが、厳密な定義は複雑なので、機械語を扱う場合には、レジスタ、メモリ、即値などを表しているとイメージすれば分かりやすいと思います。文章だけだと理解しにくいので例を提示します。

MOV EAX, 0 ←ディスティネーションオペランドであるEAXレジスタの値に、ソースオペランド(即値:0)を設定する。 
EAX=0 ADD EAX, 10 ←ディスティネーションオペランドであるEAXレジスタの値に、ソースオペランド(即値:10)を加算する。
EAX=10 SUB EAX, 5 ←ディスティネーションオペランドであるEAXレジスタの値から、ソースオペランド(即値:5)を減算する。
EAX=5

 ところが、今回実装するMUL命令は次の形式の命令です。

MUL ソースオペランド

 このようにディスティネーションオペランドがないので、今までの算術とは違い、結果を保存する場所が指定できません。ではどこへ結果が保存されるのかというと、MUL命令ではAL(1バイトの場合)かEAX(ダブルワードの場合)に固定されています。

 さらに、ソースオペランドには今までのように即値を指定することができず、レジスタかメモリを指定せねばなりません。ソースオペランドにレジスタを指定するには、命令フォーマットの概念を理解する必要がありますので、次項でそれを説明します。

命令フォーマット

 機械語の命令は0と1の羅列ですので、CPUがそれを解釈するためにフォーマットが定められています。それを命令フォーマットと呼びます。今までの命令は次の命令フォーマットでバイナリ指定してしました。

オペコード(1または2バイト) 即値(1バイトまたは4バイト)

 しかし、MULの場合は次の命令フォーマットにしなくてはなりません。

オペコード(1または2バイト) ModR/M(1バイト)

 ModR/Mでは、レジスタ、メモリのアドレス指定方式などの情報を指定します。なお、オペコードの次の項目はオペコードによって決まっています。例えばADD命令が複数あるのは次の要素を指定するためなのです。今回はメモリについては扱いませんので、次項でModR/Mでレジスタ指定方法を実装します。


プロフィール
インドリ インドリ

分析・設計・実装なんでもありのフリーエンジニア。
ブログ「無差別に技術をついばむ鳥(http://indori.blog32.fc2.com/)」の作者です。

アドバイザーをしたり、システム開発したり、情報処理技術を研究したりと色々しています。

座右の銘は温故知新で、新旧関係なく必要だと考えたものは全て学習しています。

 


記事へのコメント・トラックバック機能は2011年6月に廃止させていただきました。記事に対する反響はTwitterやFacebook、ソーシャルブックマークサービスのコメントなどでぜひお寄せください。

スポンサーサイト