1234949SbaptThe perl scripts in this directory are my 'hack' to generate
2234949Sbaptmultiple different assembler formats via the one origional script.
3234949Sbapt
4234949SbaptThe way to use this library is to start with adding the path to this directory
5234949Sbaptand then include it.
6234949Sbapt
7234949Sbaptpush(@INC,"perlasm","../../perlasm");
8234949Sbaptrequire "x86asm.pl";
9234949Sbapt
10234949SbaptThe first thing we do is setup the file and type of assember
11234949Sbapt
12234949Sbapt&asm_init($ARGV[0],$0);
13234949Sbapt
14234949SbaptThe first argument is the 'type'.  Currently
15234949Sbapt'cpp', 'sol', 'a.out', 'elf' or 'win32'.
16234949SbaptArgument 2 is the file name.
17234949Sbapt
18234949SbaptThe reciprocal function is
19234949Sbapt&asm_finish() which should be called at the end.
20234949Sbapt
21234949SbaptThere are 2 main 'packages'. x86ms.pl, which is the microsoft assembler,
22234949Sbaptand x86unix.pl which is the unix (gas) version.
23234949Sbapt
24234949SbaptFunctions of interest are:
25234949Sbapt&external_label("des_SPtrans");	declare and external variable
26234949Sbapt&LB(reg);			Low byte for a register
27234949Sbapt&HB(reg);			High byte for a register
28234949Sbapt&BP(off,base,index,scale)	Byte pointer addressing
29234949Sbapt&DWP(off,base,index,scale)	Word pointer addressing
30234949Sbapt&stack_push(num)		Basically a 'sub esp, num*4' with extra
31234949Sbapt&stack_pop(num)			inverse of stack_push
32234949Sbapt&function_begin(name,extra)	Start a function with pushing of
33234949Sbapt				edi, esi, ebx and ebp.  extra is extra win32
34234949Sbapt				external info that may be required.
35234949Sbapt&function_begin_B(name,extra)	Same as norma function_begin but no pushing.
36234949Sbapt&function_end(name)		Call at end of function.
37234949Sbapt&function_end_A(name)		Standard pop and ret, for use inside functions
38234949Sbapt&function_end_B(name)		Call at end but with poping or 'ret'.
39234949Sbapt&swtmp(num)			Address on stack temp word.
40234949Sbapt&wparam(num)			Parameter number num, that was push
41234949Sbapt				in C convention.  This all works over pushes
42234949Sbapt				and pops.
43234949Sbapt&comment("hello there")		Put in a comment.
44234949Sbapt&label("loop")			Refer to a label, normally a jmp target.
45234949Sbapt&set_label("loop")		Set a label at this point.
46234949Sbapt&data_word(word)		Put in a word of data.
47234949Sbapt
48234949SbaptSo how does this all hold together?  Given
49234949Sbapt
50234949Sbaptint calc(int len, int *data)
51234949Sbapt	{
52234949Sbapt	int i,j=0;
53234949Sbapt
54234949Sbapt	for (i=0; i<len; i++)
55234949Sbapt		{
56234949Sbapt		j+=other(data[i]);
57234949Sbapt		}
58234949Sbapt	}
59234949Sbapt
60234949SbaptSo a very simple version of this function could be coded as
61234949Sbapt
62234949Sbapt	push(@INC,"perlasm","../../perlasm");
63234949Sbapt	require "x86asm.pl";
64234949Sbapt	
65234949Sbapt	&asm_init($ARGV[0],"cacl.pl");
66234949Sbapt
67234949Sbapt	&external_label("other");
68234949Sbapt
69234949Sbapt	$tmp1=	"eax";
70234949Sbapt	$j=	"edi";
71234949Sbapt	$data=	"esi";
72234949Sbapt	$i=	"ebp";
73234949Sbapt
74234949Sbapt	&comment("a simple function");
75234949Sbapt	&function_begin("calc");
76234949Sbapt	&mov(	$data,		&wparam(1)); # data
77234949Sbapt	&xor(	$j,		$j);
78234949Sbapt	&xor(	$i,		$i);
79234949Sbapt
80234949Sbapt	&set_label("loop");
81234949Sbapt	&cmp(	$i,		&wparam(0));
82234949Sbapt	&jge(	&label("end"));
83234949Sbapt
84234949Sbapt	&mov(	$tmp1,		&DWP(0,$data,$i,4));
85234949Sbapt	&push(	$tmp1);
86234949Sbapt	&call(	"other");
87234949Sbapt	&add(	$j,		"eax");
88234949Sbapt	&pop(	$tmp1);
89234949Sbapt	&inc(	$i);
90234949Sbapt	&jmp(	&label("loop"));
91234949Sbapt
92234949Sbapt	&set_label("end");
93234949Sbapt	&mov(	"eax",		$j);
94
95	&function_end("calc");
96
97	&asm_finish();
98
99The above example is very very unoptimised but gives an idea of how
100things work.
101
102There is also a cbc mode function generator in cbc.pl
103
104&cbc(	$name,
105	$encrypt_function_name,
106	$decrypt_function_name,
107	$true_if_byte_swap_needed,
108	$parameter_number_for_iv,
109	$parameter_number_for_encrypt_flag,
110	$first_parameter_to_pass,
111	$second_parameter_to_pass,
112	$third_parameter_to_pass);
113
114So for example, given
115void BF_encrypt(BF_LONG *data,BF_KEY *key);
116void BF_decrypt(BF_LONG *data,BF_KEY *key);
117void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
118        BF_KEY *ks, unsigned char *iv, int enc);
119
120&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
121
122&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
123&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
124
125