Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

VB.NETで仮想CPUを作ろう (9) - INC命令&DEC命令の実装と命令長

VB.NETで学ぶ機械語の基礎 第9回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/10/10 14:00

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

目次

はじめに

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

 今回はINC命令とDEC命令の実装を通じて、長さが違う機械語の実装法を解説します。

これまでの連載

下準備

 前回の実装を拡張していきますので、あらかじめ前回までの部分の実装を済ませておいてください。後は専門用語とCPU構造の確認のため、前回用意した3つのIntel社のマニュアルをすぐ読める状態にしてください。

 それに加えて、中巻 B: 命令セット・リファレンス N-ZのA-6とA-7ページを印刷しておくことをお勧めします。この表をあらかじめ印刷しておき、その紙を参照しながら実装作業をすると効率がよくなります。

機械語の命令長について

 今回まで紹介してきた機械語の命令はどれも2バイト(命令1バイト+即値1バイト)もしくは5バイト(命令1バイト+即値4バイト)でした。しかし、実のところすべての命令がそうではありません。命令を表すのに2バイト必要な命令もあれば、メモリを使用する場合に、即値の他にメモリアドレスなどの値を指定したりすることもあります。

 機械語ではこのように必要とするバイト数がその都度変化します。

 すべての機械語が個定数だと便利なのですが、CPUの製造メーカーが完璧な命令を実装できるわけではありませんし、過去のプログラムを動かすための互換性維持などのさまざまな理由で長さを一定に保てません。

 それに、命令の長さが変化することに利点もあります。それは、パフォーマンス向上効果です。よく使われる命令を少ないバイト数で表現できれば、すべての命令が個定数の時は違って、全体としての無駄なバイトを減らすことができ、その結果パフォーマンスの向上をもたらします。

 なお、命令が必要とするバイト数を命令長と呼びます。

命令長への対応

 命令長が異なる命令を扱うには、まず「命令長」の情報が必要となります。その命令長はどこに属するべきかと言うと、命令を表現しているOpeCode構造体です。始めから複雑な処理を考えるとよい結果を生みませんので、プロパティとして実装することにします。OpeCodeメソッドにコメントを追加して掲載します。

OpeCode構造体
Public Structure OpeCode

    '命令の名前
    Private m_cmd As CommandName
    Public Property Name() As CommandName
        Get
            Return Me.m_cmd
        End Get
        Set(ByVal value As CommandName)
            Me.m_cmd = value
        End Set
    End Property

    '処理対象とするレジスタ
    Private m_reg As RegisterName
    Public Property Destination() As RegisterName
        Get
            Return Me.m_reg
        End Get
        Set(ByVal value As RegisterName)
            Me.m_reg = value
        End Set
    End Property

    '現在どのビット数の値を扱っているのかわかった方がいいです
    Private m_bit As Byte
    Public Property BitCount() As Byte
        Get
            Return m_bit
        End Get
        Set(ByVal value As Byte)
            m_bit = value
        End Set
    End Property

    '8ビットの場合、上位アドレスなのかの情報がいる。
    Private m_hi As Boolean
    Public Property IsHi()
        Get
            Return Me.m_hi
        End Get
        Set(ByVal value)
            Me.m_hi = True
        End Set
    End Property

    'レジスタの値
    Private m_val As Register
    Public Property Value() As Register
        Get
            Return Me.m_val
        End Get
        Set(ByVal value As Register)
            Me.m_val = value
        End Set
    End Property

    '命令長
    Private m_length As Byte
    Public Property Length() As Byte
        Get
            Return Me.m_length
        End Get
        Set(ByVal value As Byte)
            Me.m_length = value
        End Set
    End Property
End Structure

 今回はより分かりやすいように、すべてのプロパティに説明を加えました。実務ではコメントは重要で、簡単で説明がなくても分かるというコードでもひとことぐらいは書いておきます。そうしないと、実装した人には当たり前のことでも、何年も経った後に他者が修正を加える場合などに困ってしまうからです。

 実務と趣味のコーディングの違いは、「他者を意識する」ということです。常に他者から見ても分かるかを意識してコーディングをしましょう。 実はOpeCode構造体以外にも命令長を保持するべきクラスがあるのですが、今説明すると分かりにくいので、今までの命令に対して命令長の情報を付加する方法を考えます。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • インドリ(インドリ)

    分析・設計・実装なんでもありのフリーエンジニア。 ブログ「無差別に技術をついばむ鳥(http://indori.blog32.fc2.com/)」の作者です。 アドバイザーをしたり、システム開発したり、情報処理技術を研究したりと色々しています。 座右の銘は温故知新で、新旧関係なく必要だと考えた...

バックナンバー

連載:VB.NETで学ぶ機械語の基礎

もっと読む

All contents copyright © 2005-2017 Shoeisha Co., Ltd. All rights reserved. ver.1.5