Adam Langley | d9e397b | 2015-01-22 14:27:53 -0800 | [diff] [blame] | 1 | The perl scripts in this directory are my 'hack' to generate |
| 2 | multiple different assembler formats via the one origional script. |
| 3 | |
| 4 | The way to use this library is to start with adding the path to this directory |
| 5 | and then include it. |
| 6 | |
| 7 | push(@INC,"perlasm","../../perlasm"); |
| 8 | require "x86asm.pl"; |
| 9 | |
Robert Sloan | a94fe05 | 2017-02-21 08:49:28 -0800 | [diff] [blame] | 10 | The first thing we do is setup the file and type of assembler |
Adam Langley | d9e397b | 2015-01-22 14:27:53 -0800 | [diff] [blame] | 11 | |
| 12 | &asm_init($ARGV[0],$0); |
| 13 | |
| 14 | The first argument is the 'type'. Currently |
| 15 | 'cpp', 'sol', 'a.out', 'elf' or 'win32'. |
| 16 | Argument 2 is the file name. |
| 17 | |
| 18 | The reciprocal function is |
| 19 | &asm_finish() which should be called at the end. |
| 20 | |
Robert Sloan | a94fe05 | 2017-02-21 08:49:28 -0800 | [diff] [blame] | 21 | There are 2 main 'packages'. x86ms.pl, which is the Microsoft assembler, |
Adam Langley | d9e397b | 2015-01-22 14:27:53 -0800 | [diff] [blame] | 22 | and x86unix.pl which is the unix (gas) version. |
| 23 | |
| 24 | Functions of interest are: |
| 25 | &external_label("des_SPtrans"); declare and external variable |
| 26 | &LB(reg); Low byte for a register |
| 27 | &HB(reg); High byte for a register |
| 28 | &BP(off,base,index,scale) Byte pointer addressing |
| 29 | &DWP(off,base,index,scale) Word pointer addressing |
| 30 | &stack_push(num) Basically a 'sub esp, num*4' with extra |
| 31 | &stack_pop(num) inverse of stack_push |
| 32 | &function_begin(name,extra) Start a function with pushing of |
| 33 | edi, esi, ebx and ebp. extra is extra win32 |
| 34 | external info that may be required. |
Robert Sloan | a94fe05 | 2017-02-21 08:49:28 -0800 | [diff] [blame] | 35 | &function_begin_B(name,extra) Same as normal function_begin but no pushing. |
Adam Langley | d9e397b | 2015-01-22 14:27:53 -0800 | [diff] [blame] | 36 | &function_end(name) Call at end of function. |
| 37 | &function_end_A(name) Standard pop and ret, for use inside functions |
| 38 | &function_end_B(name) Call at end but with poping or 'ret'. |
| 39 | &swtmp(num) Address on stack temp word. |
| 40 | &wparam(num) Parameter number num, that was push |
| 41 | in C convention. This all works over pushes |
| 42 | and pops. |
| 43 | &comment("hello there") Put in a comment. |
| 44 | &label("loop") Refer to a label, normally a jmp target. |
| 45 | &set_label("loop") Set a label at this point. |
| 46 | &data_word(word) Put in a word of data. |
| 47 | |
| 48 | So how does this all hold together? Given |
| 49 | |
| 50 | int calc(int len, int *data) |
| 51 | { |
| 52 | int i,j=0; |
| 53 | |
| 54 | for (i=0; i<len; i++) |
| 55 | { |
| 56 | j+=other(data[i]); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | So a very simple version of this function could be coded as |
| 61 | |
| 62 | push(@INC,"perlasm","../../perlasm"); |
| 63 | require "x86asm.pl"; |
| 64 | |
| 65 | &asm_init($ARGV[0],"cacl.pl"); |
| 66 | |
| 67 | &external_label("other"); |
| 68 | |
| 69 | $tmp1= "eax"; |
| 70 | $j= "edi"; |
| 71 | $data= "esi"; |
| 72 | $i= "ebp"; |
| 73 | |
| 74 | &comment("a simple function"); |
| 75 | &function_begin("calc"); |
| 76 | &mov( $data, &wparam(1)); # data |
| 77 | &xor( $j, $j); |
| 78 | &xor( $i, $i); |
| 79 | |
| 80 | &set_label("loop"); |
| 81 | &cmp( $i, &wparam(0)); |
| 82 | &jge( &label("end")); |
| 83 | |
| 84 | &mov( $tmp1, &DWP(0,$data,$i,4)); |
| 85 | &push( $tmp1); |
| 86 | &call( "other"); |
| 87 | &add( $j, "eax"); |
| 88 | &pop( $tmp1); |
| 89 | &inc( $i); |
| 90 | &jmp( &label("loop")); |
| 91 | |
| 92 | &set_label("end"); |
| 93 | &mov( "eax", $j); |
| 94 | |
| 95 | &function_end("calc"); |
| 96 | |
| 97 | &asm_finish(); |
| 98 | |
| 99 | The above example is very very unoptimised but gives an idea of how |
| 100 | things work. |