SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

VB.NETで仮想CPUを作ろう (7) - ADD命令実装

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

  • X ポスト
  • このエントリーをはてなブックマークに追加

ADD命令の実装

 実装する前に、まずはADD命令について説明します。ADD命令は加算(足し算)を行う命令です。しかし、人間とは違いCPUは些細な事が問題となります。ADD命令では限界値をオーバーした場合どうするのかが問題となります。文章だけでは分かりにくいので例を挙げて説明します。

 例えば、ALレジスタ(1バイト)にADD命令を適用するにあたり、下記のような場合はどうなるでしょうか?

  1. MOV命令を使って0で初期化する。AL=0.
  2. ADD al, 200: ALに200を足します。AL=200.
  3. ADD al, 200: ALに再び200を足します。ALは255までしか扱えないので問題発生!

 この例の様な状況の時Intel社のCPUは、CF(キャリーフラグ)というフラグを1にして桁あふれ(オーバーフロー)した事を外部に知らせます。そして、余分なビットを無視します。

ですから、上記例3の場合は

200(2進表記で1100 1000)+
200(2進表記で1100 1000)
=400(2新表記で1 1001 0000)

 で答えが9ビットになってしまうので、余分な先頭1ビット無視して、答えを144(2新表記で1001 0000)にし、CF=1にします。

 これを表現するためには、IntelCpuオブジェクトに新しいプロパティとフィールドが必要になります。次のプロパティとフィールドを追加してください。

'オーバーフローを知らせるフラグ
Private m_cf As Boolean = False
Public Property CF() As Boolean
    Get
        Return Me.m_cf
    End Get
    Private Set(ByVal value As Boolean)
        Me.m_cf = value
    End Set
End Property

 桁あふれに注意しながらADD命令を実装すると、次のとおりになります。

'ADD命令の実装
Private Sub Add(ByVal ope As OpeCode)
    Select Case ope.Destination
        Case RegisterName.AL
            Dim tmp As UShort = Me.AL + CUShort(ope.Value.ValueLowByte)
            If Byte.MaxValue >= tmp Then
                Me.AL = tmp
            Else '桁あふれ(オーバーフロー)が発生
                Me.CF = True
                '上位ビットを消す
                tmp = tmp And &HFF
                '計算結果を設定
                Me.AL = CByte(tmp)
            End If
        Case RegisterName.EAX
            Dim tmp As ULong = Me.EAX + CULng(ope.Value.ValueU32)
            If UInteger.MaxValue >= tmp Then
                Me.CF = False
                Me.EAX = tmp
            Else '桁あふれ(オーバーフロー)が発生
                Me.CF = True
                '上位ビットを消す
                tmp = tmp And UInteger.MaxValue
                '計算結果を設定
                Me.EAX = CUInt(tmp)
            End If
    End Select
End Sub

 では実装内容を説明します。まず、対象レジスタの現在値と指定された値を加算します。この時注意しなくてはならないのは「直接レジスタプロパティに加算してはならない」ことと、「オーバーフロー対策のために、レジスタプロパティよりも大きな値が格納できる型を使用する」ことです。これは、オーバーフローが発生する可能性があるからです。もしオーバーフローが発生してしまうと、例外がスローされてしまいます。そうならないためには一時的に、大きな値を格納できる型が必要となります。

 次に必要なのは、オーバーフローのチェックとオーバーフロー時の対応です。先ほど説明したように、ADD命令ではオーバーフローが発生した際には余分なビットを切り捨てて、CFフラグを1(True)にしなくてはなりません。そのためには、ビットごとのAnd論理和を使用します。

※注
 CF以外のフラグもありますが、理解の妨げになりますので今回は実装しません。

 この大まかな流れが分かれば、ADD命令の実装を理解出来ます。しかし、ひとつだけVB.NETの性質が影響する注意点があります。それはこのプログラムです。

tmp = tmp And UInteger.MaxValue

 今まで筆者は&HFFFFというふうに16進数で指定していましたが、今回はそれができません。何故かというと、VB.NETでは「&H」はInteger型だと見なされているからです。それゆえ、今回のUInteger型のビットは得られませんので、仕方がなくUInteger.MaxValueプロパティを使用する事にしました。バイナリプロプログラミングでは、常に桁数が重要となってくるのです。

 これでIntelCpuオブジェクトのADD命令の実装が終わりましたので、次はテストドライバ側の変更を行います。

次のページ
テストドライバ側の変更

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
VB.NETで学ぶ機械語の基礎連載記事一覧

もっと読む

この記事の著者

インドリ(インドリ)

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/2895 2010/04/27 12:01

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング