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