t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

【紹介記事】VBAでマシン語(機械語≓アセンブラ)を実行する

前々回で紹介したVBAHaskellは、実行にdllを必要とする。
thom.hateblo.jp

VBAの機能で実現できないことをC++が補っている形である。
例えば、ポインタによる変数の付け替えである。

例えば次のコード

a = "Hello"
b = "GoodBye"

変数とメモリは、こんな感じになっている。

変数と番地の対応付け

変数名 メモリ番地
a 0001
b 0002

番地に入っている値

メモリ番地
0001 "Hello"
0002 "GoodBye"

VBだけでaとbの中身を交換するには、cを用意して一旦"GoodBye"を退避させたあと、bに"Hello"をコピーし、cに退避した"GoodBye"をaにコピーする。
つまり、実体をコピーする必要があるので、データが大きければその分時間がかかる。
まぁ現代のコンピュータでそれが問題になるケースというのは相当レアであるが、ライブラリとして公にする場合はそうしたケースも想定せざるを得ない。

ポインタによる付け替えというのは、以下のように指してる番地をスルッと入れ替えてしまうワザである。
変数と番地の対応付け変更

変数名 メモリ番地
a 0002
b 0001

そうするとaは"GoodBye"を指し、bは"Hello"を指すようになる。
データがどれだけ大きくても、番地のサイズはたかだか知れているので非常に効率が良い。

これをVBAだけで何とか完結する方法ないかなと探していたら、解決の糸口となる記事を見つけた。
(ただし今の私の実力では実装は困難である。)

さて、その方法は、VBAからマシン語を実行しようというもの。

【参考】
VB で機械語を実行する - Programming Field

原理を簡単に解説する。
まず、kernel32.dllのCopyMemory命令を使えば、メモリ上に任意のバイナリを展開できる。
これを利用し、VBAマシン語関数のバイナリをつくり、CopyMemoryでメモリに展開する。
メモリ上に展開した関数をVBAから呼び出す。

CやC++で作成されたコードはコンパイルしてしまえば所詮ただのバイナリ(機械語)なので、機械語をメモリ上に展開できるということはつまり任意のCやC++コードを実行できるのと同等である。

とまあ、原理自体は単純。
でも本当にそんなことができるのか。。

試しに上記サイトのコードをVBEに貼り付けて実行してみた。

まずはサイトから以下で始まる長いコード(コメント空白込み136行)をコピーしてModule1に貼り付け。

' メモリ上に関数を作るために使用する関数
Public Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" _
    (ByRef Destination As Any, ByRef Source As Any, _
    ByVal Length As Long)

'~以下略~

次に以下で始まる長いコード(コメント空白込み97行)をコピーしてModule2に貼り付け。

' DLL の関数アドレスを取得するのに使用
Private Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" _
    (ByVal lpLibFileName As String) As Long

'~以下略~

そして次に呼び出し。

Sub Test()
    Debug.Print MyWPrintF("Result: %d, %1.3lf", 12, CDbl(1.245))
End Sub

すると、解説のとおりResult: 12, 1.25と表示される。
記事はVB6を対象にしているが、ちゃんとVBAでも動くことが分かった。
いやはや、凄いことを考えた人がいたもんだ。。

(64bitOSは環境が無いので未検証ですが、動かないかもしれません。)

ただ、これを流用してポインタによるスワップを実現するためにはアセンブラの学習が必要で、一筋縄ではいかない。

独習アセンブラ

独習アセンブラ

ここから先は他力本願である。
VBAHaskellのmmYYmmddさんがいつかdll不要版を作ってくれたりしないかとひそかに期待している。
mmyymmdd.hatenablog.com

以下、今回参考にしたサイト等の紹介

今回参照にしたサイトのトップページ
Programming Field

作者:ジェットさん

過去にブログも書かれていたようで、更新は止まっても色あせない良質の記事が多い。
http://pg-torch-ic.jugem.jp/pg-torch-ic.jugem.jp

私のブログで100記事達成のときに、「たとえブログの更新がとまっても、書いた記事が、たった一人にでも、たとえ10年かかっても、本当にその情報を必要とする人に届けば、そのブログは無駄ではない。」と書いたけれど、まさにこういったブログ・サイトのことである。
thom.hateblo.jp

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。