./index.html ../index.html

ObjectPascal Magic Programming
.obj

黙って以下のファイルを用意する事。

sysinit.nas

section .CODE USE32 CLASS=CODE ALIGN=256

global @@HandleFinally
@@HandleFinally:
	ret

system.nas

section .CODE USE32 CLASS=CODE ALIGN=256

徐にコマンドプロンプトを開きnasmwでアセンブル。

...>nasmw -fobj sysinit.nas

...>nasmw -fobj system.nas

肝心のPascalソースはこんな感じだ。

obj.pas

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の置き換え用コードは、リンクエラーを解決するためだけのものなので、例外処理は一切使えません。 本式に用意すれば可能かもしれませんが…。

呼び出しもとはこんな感じ。まあ普通。

entry.c

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が機能不足なのかは定かではない。