1*b077aed3SPierre ProncheryPerl scripts for assembler sources 2*b077aed3SPierre Pronchery================================== 3*b077aed3SPierre Pronchery 4*b077aed3SPierre ProncheryThe perl scripts in this directory are my 'hack' to generate 5*b077aed3SPierre Proncherymultiple different assembler formats via the one original script. 6*b077aed3SPierre Pronchery 7*b077aed3SPierre ProncheryThe way to use this library is to start with adding the path to this directory 8*b077aed3SPierre Proncheryand then include it. 9*b077aed3SPierre Pronchery 10*b077aed3SPierre Pronchery push(@INC,"perlasm","../../perlasm"); 11*b077aed3SPierre Pronchery require "x86asm.pl"; 12*b077aed3SPierre Pronchery 13*b077aed3SPierre ProncheryThe first thing we do is setup the file and type of assembler 14*b077aed3SPierre Pronchery 15*b077aed3SPierre Pronchery &asm_init($ARGV[0]); 16*b077aed3SPierre Pronchery 17*b077aed3SPierre ProncheryThe first argument is the 'type'. Currently 18*b077aed3SPierre Pronchery`cpp`, `sol`, `a.out`, `elf` or `win32`. 19*b077aed3SPierre ProncheryThe second argument is the file name. 20*b077aed3SPierre Pronchery 21*b077aed3SPierre ProncheryThe reciprocal function is 22*b077aed3SPierre Pronchery`&asm_finish()` which should be called at the end. 23*b077aed3SPierre Pronchery 24*b077aed3SPierre ProncheryThere are two main 'packages'. `x86ms.pl`, which is the Microsoft assembler, 25*b077aed3SPierre Proncheryand `x86unix.pl` which is the unix (gas) version. 26*b077aed3SPierre Pronchery 27*b077aed3SPierre ProncheryFunctions of interest are: 28*b077aed3SPierre Pronchery 29*b077aed3SPierre Pronchery &external_label("des_SPtrans"); declare and external variable 30*b077aed3SPierre Pronchery &LB(reg); Low byte for a register 31*b077aed3SPierre Pronchery &HB(reg); High byte for a register 32*b077aed3SPierre Pronchery &BP(off,base,index,scale) Byte pointer addressing 33*b077aed3SPierre Pronchery &DWP(off,base,index,scale) Word pointer addressing 34*b077aed3SPierre Pronchery &stack_push(num) Basically a 'sub esp, num*4' with extra 35*b077aed3SPierre Pronchery &stack_pop(num) inverse of stack_push 36*b077aed3SPierre Pronchery &function_begin(name,extra) Start a function with pushing of 37*b077aed3SPierre Pronchery edi, esi, ebx and ebp. extra is extra win32 38*b077aed3SPierre Pronchery external info that may be required. 39*b077aed3SPierre Pronchery &function_begin_B(name,extra) Same as normal function_begin but no 40*b077aed3SPierre Pronchery pushing. 41*b077aed3SPierre Pronchery &function_end(name) Call at end of function. 42*b077aed3SPierre Pronchery &function_end_A(name) Standard pop and ret, for use inside 43*b077aed3SPierre Pronchery functions. 44*b077aed3SPierre Pronchery &function_end_B(name) Call at end but with pop or ret. 45*b077aed3SPierre Pronchery &swtmp(num) Address on stack temp word. 46*b077aed3SPierre Pronchery &wparam(num) Parameter number num, that was push in 47*b077aed3SPierre Pronchery C convention. This all works over pushes 48*b077aed3SPierre Pronchery and pops. 49*b077aed3SPierre Pronchery &comment("hello there") Put in a comment. 50*b077aed3SPierre Pronchery &label("loop") Refer to a label, normally a jmp target. 51*b077aed3SPierre Pronchery &set_label("loop") Set a label at this point. 52*b077aed3SPierre Pronchery &data_word(word) Put in a word of data. 53*b077aed3SPierre Pronchery 54*b077aed3SPierre ProncherySo how does this all hold together? Given 55*b077aed3SPierre Pronchery 56*b077aed3SPierre Pronchery int calc(int len, int *data) 57*b077aed3SPierre Pronchery { 58*b077aed3SPierre Pronchery int i,j=0; 59*b077aed3SPierre Pronchery 60*b077aed3SPierre Pronchery for (i=0; i<len; i++) 61*b077aed3SPierre Pronchery { 62*b077aed3SPierre Pronchery j+=other(data[i]); 63*b077aed3SPierre Pronchery } 64*b077aed3SPierre Pronchery } 65*b077aed3SPierre Pronchery 66*b077aed3SPierre ProncherySo a very simple version of this function could be coded as 67*b077aed3SPierre Pronchery 68*b077aed3SPierre Pronchery push(@INC,"perlasm","../../perlasm"); 69*b077aed3SPierre Pronchery require "x86asm.pl"; 70*b077aed3SPierre Pronchery 71*b077aed3SPierre Pronchery &asm_init($ARGV[0]); 72*b077aed3SPierre Pronchery 73*b077aed3SPierre Pronchery &external_label("other"); 74*b077aed3SPierre Pronchery 75*b077aed3SPierre Pronchery $tmp1= "eax"; 76*b077aed3SPierre Pronchery $j= "edi"; 77*b077aed3SPierre Pronchery $data= "esi"; 78*b077aed3SPierre Pronchery $i= "ebp"; 79*b077aed3SPierre Pronchery 80*b077aed3SPierre Pronchery &comment("a simple function"); 81*b077aed3SPierre Pronchery &function_begin("calc"); 82*b077aed3SPierre Pronchery &mov( $data, &wparam(1)); # data 83*b077aed3SPierre Pronchery &xor( $j, $j); 84*b077aed3SPierre Pronchery &xor( $i, $i); 85*b077aed3SPierre Pronchery 86*b077aed3SPierre Pronchery &set_label("loop"); 87*b077aed3SPierre Pronchery &cmp( $i, &wparam(0)); 88*b077aed3SPierre Pronchery &jge( &label("end")); 89*b077aed3SPierre Pronchery 90*b077aed3SPierre Pronchery &mov( $tmp1, &DWP(0,$data,$i,4)); 91*b077aed3SPierre Pronchery &push( $tmp1); 92*b077aed3SPierre Pronchery &call( "other"); 93*b077aed3SPierre Pronchery &add( $j, "eax"); 94*b077aed3SPierre Pronchery &pop( $tmp1); 95*b077aed3SPierre Pronchery &inc( $i); 96*b077aed3SPierre Pronchery &jmp( &label("loop")); 97*b077aed3SPierre Pronchery 98*b077aed3SPierre Pronchery &set_label("end"); 99*b077aed3SPierre Pronchery &mov( "eax", $j); 100*b077aed3SPierre Pronchery 101*b077aed3SPierre Pronchery &function_end("calc"); 102*b077aed3SPierre Pronchery 103*b077aed3SPierre Pronchery &asm_finish(); 104*b077aed3SPierre Pronchery 105*b077aed3SPierre ProncheryThe above example is very very unoptimised but gives an idea of how 106*b077aed3SPierre Proncherythings work. 107*b077aed3SPierre Pronchery 108*b077aed3SPierre ProncheryThere is also a cbc mode function generator in cbc.pl 109*b077aed3SPierre Pronchery 110*b077aed3SPierre Pronchery &cbc($name, 111*b077aed3SPierre Pronchery $encrypt_function_name, 112*b077aed3SPierre Pronchery $decrypt_function_name, 113*b077aed3SPierre Pronchery $true_if_byte_swap_needed, 114*b077aed3SPierre Pronchery $parameter_number_for_iv, 115*b077aed3SPierre Pronchery $parameter_number_for_encrypt_flag, 116*b077aed3SPierre Pronchery $first_parameter_to_pass, 117*b077aed3SPierre Pronchery $second_parameter_to_pass, 118*b077aed3SPierre Pronchery $third_parameter_to_pass); 119*b077aed3SPierre Pronchery 120*b077aed3SPierre ProncherySo for example, given 121*b077aed3SPierre Pronchery 122*b077aed3SPierre Pronchery void BF_encrypt(BF_LONG *data,BF_KEY *key); 123*b077aed3SPierre Pronchery void BF_decrypt(BF_LONG *data,BF_KEY *key); 124*b077aed3SPierre Pronchery void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length, 125*b077aed3SPierre Pronchery BF_KEY *ks, unsigned char *iv, int enc); 126*b077aed3SPierre Pronchery 127*b077aed3SPierre Pronchery &cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1); 128*b077aed3SPierre Pronchery 129*b077aed3SPierre Pronchery &cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1); 130*b077aed3SPierre Pronchery &cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5); 131