黙って以下のファイルを用意する事。
section .CODE USE32 CLASS=CODE ALIGN=256 global @@HandleFinally @@HandleFinally: ret
section .CODE USE32 CLASS=CODE ALIGN=256
徐にコマンドプロンプトを開きnasmwでアセンブル。
...>nasmw -fobj sysinit.nas ...>nasmw -fobj system.nas
肝心のPascalソースはこんな感じだ。
unit obj; interface procedure TEST1; pascal; implementation function MessageBoxA(A: Integer; B: PChar; C: PChar; D: Integer): Integer; stdcall; external 'user32.dll'; procedure TEST1; begin MessageBoxA(0, 'aaa', 'bbb', 0); end; end.
注意事項として、決してSystem.pasに頼ってはいけない。
明示的な関数呼出しだけでは無く、暗黙に呼ばれるルーチンも駄目。
即ち動的にメモリを確保する型は全滅。TObjectや動的配列どころかstringすら。
例外処理も不可。使えるのはTurboPascal機能のみ。
APIはOK。
しかしWindows.pasをusesしてはいけない。ライブラリは一切使えない。
必要なものは自分で書くか{$L xxx}でリンクする。
initialization/finalization/初期化または終了処理が必要な型の静的変数を持つunitをusesしてはいけない。
SysUtils.pasやClasses.pasはダメ。
Windows.pasなら(試してないけど恐らく)可能。
他言語モジュールの.objを{$L xxx}でリンクするのは問題無い。
まあこの辺は、QuickBASICとCとアセンブラでミックスランゲージなMS-DOS時代では普通の話だったので、詳しくは立ち入らない。
あと、冒頭のsysinit.pasの置き換え用コードは、リンクエラーを解決するためだけのものなので、例外処理は一切使えません。 本式に用意すれば可能かもしれませんが…。
呼び出しもとはこんな感じ。まあ普通。
extern void __pascal TEST1(void); int main() { TEST1(); return 0; }
とりゃあ。
...>dcc32 -j obj.pas Borland Delphi Version 14.0 Copyright (c) 1983,2002 Borland Software Corporation obj.pas(17) 18 lines, 0.03 seconds, 88 bytes code, 4 bytes data. ...>bcc32 entry.c obj.obj Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland entry.c: Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
起動するとこんな感じ。
僕が嘘をついているかどうか、信じるかどうかは貴方に委ねる。
Borland C++からだけでは無く、エントリも全てnasmwで書く事にも成功している。ということはOMF形式の.objをリンクできる言語であれば呼べるという事。
ただしALINKではリンクできなかった。
リンカはilink32に限定なのか、それとも単にALINKが機能不足なのかは定かではない。
2002-01-22 | 成功してしまった… |
2003-12-12 | 追記と改題 |