xref: /openbsd-src/lib/libcrypto/perlasm/readme (revision 71743258a3166741cf8441ad610c50453f062da3)
15b37fcf3SrykerThe perl scripts in this directory are my 'hack' to generate
2*71743258Sjmcmultiple different assembler formats via the one original script.
35b37fcf3Sryker
45b37fcf3SrykerThe way to use this library is to start with adding the path to this directory
55b37fcf3Srykerand then include it.
65b37fcf3Sryker
75b37fcf3Srykerpush(@INC,"perlasm","../../perlasm");
85b37fcf3Srykerrequire "x86asm.pl";
95b37fcf3Sryker
10c34dff35SderaadtThe first thing we do is setup the file and type of assembler
115b37fcf3Sryker
125b37fcf3Sryker&asm_init($ARGV[0],$0);
135b37fcf3Sryker
145b37fcf3SrykerThe first argument is the 'type'.  Currently
155b37fcf3Sryker'cpp', 'sol', 'a.out', 'elf' or 'win32'.
165b37fcf3SrykerArgument 2 is the file name.
175b37fcf3Sryker
185b37fcf3SrykerThe reciprocal function is
195b37fcf3Sryker&asm_finish() which should be called at the end.
205b37fcf3Sryker
215b37fcf3SrykerThere are 2 main 'packages'. x86ms.pl, which is the microsoft assembler,
225b37fcf3Srykerand x86unix.pl which is the unix (gas) version.
235b37fcf3Sryker
245b37fcf3SrykerFunctions of interest are:
255b37fcf3Sryker&external_label("des_SPtrans");	declare and external variable
265b37fcf3Sryker&LB(reg);			Low byte for a register
275b37fcf3Sryker&HB(reg);			High byte for a register
285b37fcf3Sryker&BP(off,base,index,scale)	Byte pointer addressing
295b37fcf3Sryker&DWP(off,base,index,scale)	Word pointer addressing
305b37fcf3Sryker&stack_push(num)		Basically a 'sub esp, num*4' with extra
315b37fcf3Sryker&stack_pop(num)			inverse of stack_push
325b37fcf3Sryker&function_begin(name,extra)	Start a function with pushing of
335b37fcf3Sryker				edi, esi, ebx and ebp.  extra is extra win32
345b37fcf3Sryker				external info that may be required.
355b37fcf3Sryker&function_begin_B(name,extra)	Same as norma function_begin but no pushing.
365b37fcf3Sryker&function_end(name)		Call at end of function.
375b37fcf3Sryker&function_end_A(name)		Standard pop and ret, for use inside functions
385b37fcf3Sryker&function_end_B(name)		Call at end but with poping or 'ret'.
395b37fcf3Sryker&swtmp(num)			Address on stack temp word.
405b37fcf3Sryker&wparam(num)			Parameter number num, that was push
415b37fcf3Sryker				in C convention.  This all works over pushes
425b37fcf3Sryker				and pops.
435b37fcf3Sryker&comment("hello there")		Put in a comment.
445b37fcf3Sryker&label("loop")			Refer to a label, normally a jmp target.
455b37fcf3Sryker&set_label("loop")		Set a label at this point.
465b37fcf3Sryker&data_word(word)		Put in a word of data.
475b37fcf3Sryker
485b37fcf3SrykerSo how does this all hold together?  Given
495b37fcf3Sryker
505b37fcf3Srykerint calc(int len, int *data)
515b37fcf3Sryker	{
525b37fcf3Sryker	int i,j=0;
535b37fcf3Sryker
545b37fcf3Sryker	for (i=0; i<len; i++)
555b37fcf3Sryker		{
565b37fcf3Sryker		j+=other(data[i]);
575b37fcf3Sryker		}
585b37fcf3Sryker	}
595b37fcf3Sryker
605b37fcf3SrykerSo a very simple version of this function could be coded as
615b37fcf3Sryker
625b37fcf3Sryker	push(@INC,"perlasm","../../perlasm");
635b37fcf3Sryker	require "x86asm.pl";
645b37fcf3Sryker
655b37fcf3Sryker	&asm_init($ARGV[0],"cacl.pl");
665b37fcf3Sryker
675b37fcf3Sryker	&external_label("other");
685b37fcf3Sryker
695b37fcf3Sryker	$tmp1=	"eax";
705b37fcf3Sryker	$j=	"edi";
715b37fcf3Sryker	$data=	"esi";
725b37fcf3Sryker	$i=	"ebp";
735b37fcf3Sryker
745b37fcf3Sryker	&comment("a simple function");
755b37fcf3Sryker	&function_begin("calc");
765b37fcf3Sryker	&mov(	$data,		&wparam(1)); # data
775b37fcf3Sryker	&xor(	$j,		$j);
785b37fcf3Sryker	&xor(	$i,		$i);
795b37fcf3Sryker
805b37fcf3Sryker	&set_label("loop");
815b37fcf3Sryker	&cmp(	$i,		&wparam(0));
825b37fcf3Sryker	&jge(	&label("end"));
835b37fcf3Sryker
845b37fcf3Sryker	&mov(	$tmp1,		&DWP(0,$data,$i,4));
855b37fcf3Sryker	&push(	$tmp1);
865b37fcf3Sryker	&call(	"other");
875b37fcf3Sryker	&add(	$j,		"eax");
885b37fcf3Sryker	&pop(	$tmp1);
895b37fcf3Sryker	&inc(	$i);
905b37fcf3Sryker	&jmp(	&label("loop"));
915b37fcf3Sryker
925b37fcf3Sryker	&set_label("end");
935b37fcf3Sryker	&mov(	"eax",		$j);
945b37fcf3Sryker
955b37fcf3Sryker	&function_end("calc");
965b37fcf3Sryker
975b37fcf3Sryker	&asm_finish();
985b37fcf3Sryker
995b37fcf3SrykerThe above example is very very unoptimised but gives an idea of how
1005b37fcf3Srykerthings work.
1015b37fcf3Sryker
1025b37fcf3SrykerThere is also a cbc mode function generator in cbc.pl
1035b37fcf3Sryker
1045b37fcf3Sryker&cbc(	$name,
1055b37fcf3Sryker	$encrypt_function_name,
1065b37fcf3Sryker	$decrypt_function_name,
1075b37fcf3Sryker	$true_if_byte_swap_needed,
1085b37fcf3Sryker	$parameter_number_for_iv,
1095b37fcf3Sryker	$parameter_number_for_encrypt_flag,
1105b37fcf3Sryker	$first_parameter_to_pass,
1115b37fcf3Sryker	$second_parameter_to_pass,
1125b37fcf3Sryker	$third_parameter_to_pass);
1135b37fcf3Sryker
1145b37fcf3SrykerSo for example, given
1155b37fcf3Srykervoid BF_encrypt(BF_LONG *data,BF_KEY *key);
1165b37fcf3Srykervoid BF_decrypt(BF_LONG *data,BF_KEY *key);
1175b37fcf3Srykervoid BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
1185b37fcf3Sryker        BF_KEY *ks, unsigned char *iv, int enc);
1195b37fcf3Sryker
1205b37fcf3Sryker&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
1215b37fcf3Sryker
1225b37fcf3Sryker&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
1235b37fcf3Sryker&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
1245b37fcf3Sryker
125