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