mirror of https://github.com/openssl/openssl.git
				
				
				
			
		
			
	
	
		
			125 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			125 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
|  | The perl scripts in this directory are my 'hack' to generate | ||
|  | multiple different assembler formats via the one origional script. | ||
|  | 
 | ||
|  | The way to use this library is to start with adding the path to this directory | ||
|  | and then include it. | ||
|  | 
 | ||
|  | push(@INC,"perlasm","../../perlasm"); | ||
|  | require "x86asm.pl"; | ||
|  | 
 | ||
|  | The first thing we do is setup the file and type of assember | ||
|  | 
 | ||
|  | &asm_init($ARGV[0],$0); | ||
|  | 
 | ||
|  | The first argument is the 'type'.  Currently | ||
|  | 'cpp', 'sol', 'a.out', 'elf' or 'win32'. | ||
|  | Argument 2 is the file name. | ||
|  | 
 | ||
|  | The reciprocal function is | ||
|  | &asm_finish() which should be called at the end. | ||
|  | 
 | ||
|  | There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler, | ||
|  | and x86unix.pl which is the unix (gas) version. | ||
|  | 
 | ||
|  | Functions of interest are: | ||
|  | &external_label("des_SPtrans");	declare and external variable | ||
|  | &LB(reg);			Low byte for a register | ||
|  | &HB(reg);			High byte for a register | ||
|  | &BP(off,base,index,scale)	Byte pointer addressing | ||
|  | &DWP(off,base,index,scale)	Word pointer addressing | ||
|  | &stack_push(num)		Basically a 'sub esp, num*4' with extra | ||
|  | &stack_pop(num)			inverse of stack_push | ||
|  | &function_begin(name,extra)	Start a function with pushing of | ||
|  | 				edi, esi, ebx and ebp.  extra is extra win32 | ||
|  | 				external info that may be required. | ||
|  | &function_begin_B(name,extra)	Same as norma function_begin but no pushing. | ||
|  | &function_end(name)		Call at end of function. | ||
|  | &function_end_A(name)		Standard pop and ret, for use inside functions | ||
|  | &function_end_B(name)		Call at end but with poping or 'ret'. | ||
|  | &swtmp(num)			Address on stack temp word. | ||
|  | &wparam(num)			Parameter number num, that was push | ||
|  | 				in C convention.  This all works over pushes | ||
|  | 				and pops. | ||
|  | &comment("hello there")		Put in a comment. | ||
|  | &label("loop")			Refer to a label, normally a jmp target. | ||
|  | &set_label("loop")		Set a label at this point. | ||
|  | &data_word(word)		Put in a word of data. | ||
|  | 
 | ||
|  | So how does this all hold together?  Given | ||
|  | 
 | ||
|  | int calc(int len, int *data) | ||
|  | 	{ | ||
|  | 	int i,j=0; | ||
|  | 
 | ||
|  | 	for (i=0; i<len; i++) | ||
|  | 		{ | ||
|  | 		j+=other(data[i]); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | So a very simple version of this function could be coded as | ||
|  | 
 | ||
|  | 	push(@INC,"perlasm","../../perlasm"); | ||
|  | 	require "x86asm.pl"; | ||
|  | 	 | ||
|  | 	&asm_init($ARGV[0],"cacl.pl"); | ||
|  | 
 | ||
|  | 	&external_label("other"); | ||
|  | 
 | ||
|  | 	$tmp1=	"eax"; | ||
|  | 	$j=	"edi"; | ||
|  | 	$data=	"esi"; | ||
|  | 	$i=	"ebp"; | ||
|  | 
 | ||
|  | 	&comment("a simple function"); | ||
|  | 	&function_begin("calc"); | ||
|  | 	&mov(	$data,		&wparam(1)); # data | ||
|  | 	&xor(	$j,		$j); | ||
|  | 	&xor(	$i,		$i); | ||
|  | 
 | ||
|  | 	&set_label("loop"); | ||
|  | 	&cmp(	$i,		&wparam(0)); | ||
|  | 	&jge(	&label("end")); | ||
|  | 
 | ||
|  | 	&mov(	$tmp1,		&DWP(0,$data,$i,4)); | ||
|  | 	&push(	$tmp1); | ||
|  | 	&call(	"other"); | ||
|  | 	&add(	$j,		"eax"); | ||
|  | 	&pop(	$tmp1); | ||
|  | 	&inc(	$i); | ||
|  | 	&jmp(	&label("loop")); | ||
|  | 
 | ||
|  | 	&set_label("end"); | ||
|  | 	&mov(	"eax",		$j); | ||
|  | 
 | ||
|  | 	&function_end("calc"); | ||
|  | 
 | ||
|  | 	&asm_finish(); | ||
|  | 
 | ||
|  | The above example is very very unoptimised but gives an idea of how | ||
|  | things work. | ||
|  | 
 | ||
|  | There is also a cbc mode function generator in cbc.pl | ||
|  | 
 | ||
|  | &cbc(	$name, | ||
|  | 	$encrypt_function_name, | ||
|  | 	$decrypt_function_name, | ||
|  | 	$true_if_byte_swap_needed, | ||
|  | 	$parameter_number_for_iv, | ||
|  | 	$parameter_number_for_encrypt_flag, | ||
|  | 	$first_parameter_to_pass, | ||
|  | 	$second_parameter_to_pass, | ||
|  | 	$third_parameter_to_pass); | ||
|  | 
 | ||
|  | So for example, given | ||
|  | void BF_encrypt(BF_LONG *data,BF_KEY *key); | ||
|  | void BF_decrypt(BF_LONG *data,BF_KEY *key); | ||
|  | void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length, | ||
|  |         BF_KEY *ks, unsigned char *iv, int enc); | ||
|  | 
 | ||
|  | &cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1); | ||
|  | 
 | ||
|  | &cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1); | ||
|  | &cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5); | ||
|  | 
 |