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