|
NAMEInline::ASM - Write Perl Subroutines in assembler.SYNOPSISprint "9 + 16 = ", add(9, 16), "\n"; print "9 - 16 = ", subtract(9, 16), "\n"; use Inline ASM => 'DATA', AS => 'as', PROTO => {add => 'int(int,int)'}; use Inline ASM => 'DATA', AS => 'nasm', ASFLAGS => '-f elf', PROTO => {subtract => 'int(int,int)'}; __END__ __ASM__ .text .globl add add: movl 4(%esp),%eax addl 8(%esp),%eax ret __ASM__ GLOBAL subtract SECTION .text subtract: mov eax,[esp+4] sub eax,[esp+8] ret DESCRIPTIONInline::ASM allows you to write Perl subroutines in assembly language. Of course, many C compilers allow you to put assembly right in your C code, so this module does not provide any new functionality. It does, however, provide a feature most C compilers don't: you can mix different assembler syntaxes in the same file!Using Inline::ASMInline::ASM is almost exactly the same as Inline::C. It makes sure the globals you requested are declared global, compiles the source code and the XS wrappers, and then creates one loadable module for each code segment.There are some shortcomings of extending Perl with assembly. Perl is written in C (and Perl), and makes heavy use of macros to provide a consistent API when it's compiled with different options. For example, the C programmer usually doesn't care if Perl is compiled with threads or without, because the all API calls are resolved to a particular Perl interpreter using macros. Inline::ASM tries to make your life simpler by overloading the PROTO or PROTOTYPE hints to do some menial macro processing for you. See ASM Configuration Options, below. Function DefinitionsInline::C uses a Parse::RecDescent grammar to find function definitions in C code. Because assembler is a much simpler syntax, and both NASM and GNU AS have pseudo-ops for declaring global symbols, Inline::ASM runs your code through a regular expression to search for the pseudo-ops.For example, in NASM, you declare global symbols like so: GLOBAL myfunction myfunction: mov eax,10 In GNU AS, you declare global symbols like so: .globl myfunction myfunction: mov $10,%eax Inline::C gets all the information it needs from your C code. In particular, it's easy to find out what to pass a function, because the function header tells you: void foo(int a, char *b) { ... } The corresponding assembler code doesn't tell you very much: foo: So Inline::ASM will only bind to symbols you ask for via the PROTO option. PROTO simply gives Inline::ASM the rest of the information about the symbol. It won't make any difference to the assembler code, but it will allow Perl to bind to it. ASM Configuration OptionsFor information on how to specify Inline configuration options, see Inline. This section describes the configuration options only available for Inline::ASM. All Inline and Inline::C options are also supported. See Inline::C for additional information.ASSpecifies the assembler command to use. Can also be used to specify flags; in the case of the GASP assembler, you must specify flags here. Any flags in ASFLAGS will be passed to GNU as, rather than GASP.ASFLAGSSpecifies flags to pass to the assembler.Supported AssemblersThese assemblers have been tested with Inline::ASM:
ASM-Perl BindingsThis section describes how the `Perl' variables get mapped to `ASM' variables and back again.Brian Ingersion (INGY@cpan.org) gives a very good description of how Perl types are translated to C types and back. That discussion is relevant to the way Inline::ASM works too, since all your variables pass through a C layer (XS) before getting to Assembler, and again on their way back to Perl. See Inline::C for that diatribe. The biggest difference between Inline::C and Inline::ASM is that you don't get the luxury of sitting in a macro-rich C environment. You have to do some work. The Perl API in Assembler (EXPERIMENTAL)If you're using any Perl API calls, you need to pass a special variable to your assembler function: pTHX. This is actually a macro in C land, magically passed to all API calls. For example, this harmless snippet of C code:return newSVpv("Hello, World!", 0); is really doing this: return Perl_newSVpv(aTHX_ "Hello, World!", 0); Depending on your setup, aTHX_ might be undefined, empty, or a PerlInterpreter structure. In the perl that ships with RedHat Linux 6.2, this becomes: return Perl_newSVpv("Hello, World!", 0); "aTHX_" is a C macro which, depending on your setup, defines either a Perl interpreter or nothing. On perl 5.005_03 on my RedHat 6.2 box, aTHX_ is resolved to "". With ActivePerl 623, aTHX_ resolves to some pthreads calls which get the currently running interpeter. Your assembler code doesn't know anything about Perl, so the user-level API is not available. You need to explicitly call "Perl_newSVpv", passing it a Perl interpreter if your Perl expects one. You can test if Perl wants a parameter running this code: use Inline C => <<END; void foo(pTHX_ int a) { printf("This perl interpreter is defined: %p\n", aTHX); return Perl_newSViv(aTHX_ a); }; END If the code compiles, Perl has been configured to pass a PerlInterpreter using the macros aTHX and pTHX. If the code fails because the macros weren't defined, or because of a parse error on the "printf" line, then the Perl interpreter is kept in a global variable and the macros aren't required. You can get Inline::ASM to pass the Perl parameter to your assembler function by asking for it like this: print "9 + 16 = ", add(9, 16), "\n"; use Inline ASM => 'DATA', AS => 'as', PROTO => {add => 'SV*(pTHX,int,int)}; __END__ .text .globl add .extern Perl_newSViv add: movl 4(%esp),%ebx movl 8(%esp),%eax addl 12(%esp),%eax pushl %eax pushl %ebx call Perl_newSViv leave ret Note that if your Perl configuration doesn't define the pTHX macro, this will cause a compile error. So basically you can't write portable assembler extensions. Of course, if you want a portable solution, use Inline::C. ExamplesExample #1 - GreetingsThis example takes a string argument (a name) and prints a greeting. The function is called with a string, then a number. Perl forces the number to a string.greet('Ingy'); greet(42); use Inline ASM => <<'END', PROTO => { greet => 'void(char*)'}; .data gstr: .string "Hello %s!\n" .text .globl greet greet: movl 4(%esp),%eax pushl %eax pushl $gstr call printf leave ret END SEE ALSOFor general information about Inline see Inline.For information on supported languages and platforms see Inline::Support. For information on writing your own Inline Language Support Module, see Inline-API. Inline's mailing list is inline@perl.org To subscribe, send email to inline-subscribe@perl.org WARNINGDo NOT use assembler to write Perl extensions! It's sick and wrong!AUTHORNeil Watkiss <NEILW@cpan.org>COPYRIGHTCopyright (c) 2001, Neil Watkiss.All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself. (see http://www.perl.com/perl/misc/Artistic.html)
Visit the GSP FreeBSD Man Page Interface. |