Inline::ASM
perlから他言語を使うInlineモジュールの中にアセンブリを扱う
Inline::ASMがあることは以前から知っていたのですが、使ったことはありませんでした。
Inline::ASM - Write Perl Subroutines in assembler. - metacpan.org
ためしに触ってみたらすんなり動かすことが出来なかったのでメモ。
SYNOPSISを信じて下のコードを動かしたらエラーが出ました。
(Win7 + Strawberry Perl + nasm)
#!perl print "9 + 16 = ", add(9, 16), "\n"; use Inline ASM => 'DATA', AS => 'nasm', PROTO => {add => 'int(int,int)'}; __DATA__ __ASM__ global add section .text add: mov eax,[esp+4] add eax,[esp+8] ret
エラー
error_pl_fbdc.o:error_pl_fbdc.c:(.text+0x601): undefined reference to `add'
アセンブリコードのシンボル名にアンダースコアつけないとダメかなと思って
つけてみましたが、また別のエラーが・・・。
エラー
Use of inherited AUTOLOAD for non-method main::add() is deprecated at error.pl line 2.
アンダースコアつけてないヤツもglobalしなきゃだめか?と思って追加してみたところうまくいきました。
#!perl print "9 + 16 = ", add(9, 16), "\n"; use Inline ASM => 'DATA', AS => 'nasm', PROTO => {add => 'int(int,int)'}; __DATA__ __ASM__ global _add global add section .text _add: mov eax,[esp+4] add eax,[esp+8] ret
出力
9 + 16 = 25
おまけでHello, World!しておきました。
#!perl use DynaLoader; my $path = "$ENV{SystemRoot}\\system32\\user32.dll"; my $libref = DynaLoader::dl_load_file($path); my $sym = DynaLoader::dl_find_symbol($libref, "MessageBoxA"); call_msgbox($sym, 0, "title", "Hello, World!", 0); use Inline ASM => 'DATA', AS => 'nasm', PROTO => {call_msgbox => 'void(long,long,char*,char*,long)'}; __END__ __ASM__ GLOBAL _call_msgbox GLOBAL call_msgbox SECTION .text _call_msgbox: mov ebx,esp mov eax,[ebx+4] push dword [ebx+8] push dword [ebx+12] push dword [ebx+16] push dword [ebx+20] call eax ret