155714SkrisThe perl scripts in this directory are my 'hack' to generate
255714Skrismultiple different assembler formats via the one origional script.
355714Skris
455714SkrisThe way to use this library is to start with adding the path to this directory
555714Skrisand then include it.
655714Skris
755714Skrispush(@INC,"perlasm","../../perlasm");
855714Skrisrequire "x86asm.pl";
955714Skris
1055714SkrisThe first thing we do is setup the file and type of assember
1155714Skris
1255714Skris&asm_init($ARGV[0],$0);
1355714Skris
1455714SkrisThe first argument is the 'type'.  Currently
1555714Skris'cpp', 'sol', 'a.out', 'elf' or 'win32'.
1655714SkrisArgument 2 is the file name.
1755714Skris
1855714SkrisThe reciprocal function is
1955714Skris&asm_finish() which should be called at the end.
2055714Skris
2155714SkrisThere are 2 main 'packages'. x86ms.pl, which is the microsoft assembler,
2255714Skrisand x86unix.pl which is the unix (gas) version.
2355714Skris
2455714SkrisFunctions of interest are:
2555714Skris&external_label("des_SPtrans");	declare and external variable
2655714Skris&LB(reg);			Low byte for a register
2755714Skris&HB(reg);			High byte for a register
2855714Skris&BP(off,base,index,scale)	Byte pointer addressing
2955714Skris&DWP(off,base,index,scale)	Word pointer addressing
3055714Skris&stack_push(num)		Basically a 'sub esp, num*4' with extra
3155714Skris&stack_pop(num)			inverse of stack_push
3255714Skris&function_begin(name,extra)	Start a function with pushing of
3355714Skris				edi, esi, ebx and ebp.  extra is extra win32
3455714Skris				external info that may be required.
3555714Skris&function_begin_B(name,extra)	Same as norma function_begin but no pushing.
3655714Skris&function_end(name)		Call at end of function.
3755714Skris&function_end_A(name)		Standard pop and ret, for use inside functions
3855714Skris&function_end_B(name)		Call at end but with poping or 'ret'.
3955714Skris&swtmp(num)			Address on stack temp word.
4055714Skris&wparam(num)			Parameter number num, that was push
4155714Skris				in C convention.  This all works over pushes
4255714Skris				and pops.
4355714Skris&comment("hello there")		Put in a comment.
4455714Skris&label("loop")			Refer to a label, normally a jmp target.
4555714Skris&set_label("loop")		Set a label at this point.
4655714Skris&data_word(word)		Put in a word of data.
4755714Skris
4855714SkrisSo how does this all hold together?  Given
4955714Skris
5055714Skrisint calc(int len, int *data)
5155714Skris	{
5255714Skris	int i,j=0;
5355714Skris
5455714Skris	for (i=0; i<len; i++)
5555714Skris		{
5655714Skris		j+=other(data[i]);
5755714Skris		}
5855714Skris	}
5955714Skris
6055714SkrisSo a very simple version of this function could be coded as
6155714Skris
6255714Skris	push(@INC,"perlasm","../../perlasm");
6355714Skris	require "x86asm.pl";
6455714Skris	
6555714Skris	&asm_init($ARGV[0],"cacl.pl");
6655714Skris
6755714Skris	&external_label("other");
6855714Skris
6955714Skris	$tmp1=	"eax";
7055714Skris	$j=	"edi";
7155714Skris	$data=	"esi";
7255714Skris	$i=	"ebp";
7355714Skris
7455714Skris	&comment("a simple function");
7555714Skris	&function_begin("calc");
7655714Skris	&mov(	$data,		&wparam(1)); # data
7755714Skris	&xor(	$j,		$j);
7855714Skris	&xor(	$i,		$i);
7955714Skris
8055714Skris	&set_label("loop");
8155714Skris	&cmp(	$i,		&wparam(0));
8255714Skris	&jge(	&label("end"));
8355714Skris
8455714Skris	&mov(	$tmp1,		&DWP(0,$data,$i,4));
8555714Skris	&push(	$tmp1);
8655714Skris	&call(	"other");
8755714Skris	&add(	$j,		"eax");
8855714Skris	&pop(	$tmp1);
8955714Skris	&inc(	$i);
9055714Skris	&jmp(	&label("loop"));
9155714Skris
9255714Skris	&set_label("end");
9355714Skris	&mov(	"eax",		$j);
9455714Skris
9555714Skris	&function_end("calc");
9655714Skris
9755714Skris	&asm_finish();
9855714Skris
9955714SkrisThe above example is very very unoptimised but gives an idea of how
10055714Skristhings work.
10155714Skris
10255714SkrisThere is also a cbc mode function generator in cbc.pl
10355714Skris
10455714Skris&cbc(	$name,
10555714Skris	$encrypt_function_name,
10655714Skris	$decrypt_function_name,
10755714Skris	$true_if_byte_swap_needed,
10855714Skris	$parameter_number_for_iv,
10955714Skris	$parameter_number_for_encrypt_flag,
11055714Skris	$first_parameter_to_pass,
11155714Skris	$second_parameter_to_pass,
11255714Skris	$third_parameter_to_pass);
11355714Skris
11455714SkrisSo for example, given
11555714Skrisvoid BF_encrypt(BF_LONG *data,BF_KEY *key);
11655714Skrisvoid BF_decrypt(BF_LONG *data,BF_KEY *key);
11755714Skrisvoid BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
11855714Skris        BF_KEY *ks, unsigned char *iv, int enc);
11955714Skris
12055714Skris&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
12155714Skris
12255714Skris&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
12355714Skris&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
12455714Skris
125