From ea1947ffcc606d757357398b24e74a3f4ecefa07 Mon Sep 17 00:00:00 2001 From: neonloop Date: Wed, 20 Oct 2021 14:54:27 +0000 Subject: Initial commit from steward-fu release --- 3rdparty/des-4.04b/asm/perlasm/cbc.pl | 342 +++++++++++++++++++++++++ 3rdparty/des-4.04b/asm/perlasm/readme | 124 +++++++++ 3rdparty/des-4.04b/asm/perlasm/x86asm.pl | 111 ++++++++ 3rdparty/des-4.04b/asm/perlasm/x86ms.pl | 345 +++++++++++++++++++++++++ 3rdparty/des-4.04b/asm/perlasm/x86unix.pl | 403 ++++++++++++++++++++++++++++++ 5 files changed, 1325 insertions(+) create mode 100644 3rdparty/des-4.04b/asm/perlasm/cbc.pl create mode 100644 3rdparty/des-4.04b/asm/perlasm/readme create mode 100644 3rdparty/des-4.04b/asm/perlasm/x86asm.pl create mode 100644 3rdparty/des-4.04b/asm/perlasm/x86ms.pl create mode 100644 3rdparty/des-4.04b/asm/perlasm/x86unix.pl (limited to '3rdparty/des-4.04b/asm/perlasm') diff --git a/3rdparty/des-4.04b/asm/perlasm/cbc.pl b/3rdparty/des-4.04b/asm/perlasm/cbc.pl new file mode 100644 index 0000000..0145c4f --- /dev/null +++ b/3rdparty/des-4.04b/asm/perlasm/cbc.pl @@ -0,0 +1,342 @@ +#!/usr/local/bin/perl + +# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) +# des_cblock (*input); +# des_cblock (*output); +# long length; +# des_key_schedule schedule; +# des_cblock (*ivec); +# int enc; +# +# calls +# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); +# + +#&cbc("des_ncbc_encrypt","des_encrypt",0); +#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt", +# 1,4,5,3,5,-1); +#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt", +# 0,4,5,3,5,-1); +#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3", +# 0,6,7,3,4,5); +# +# When doing a cipher that needs bigendian order, +# for encrypt, the iv is kept in bigendian form, +# while for decrypt, it is kept in little endian. +sub cbc + { + local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_; + # name is the function name + # enc_func and dec_func and the functions to call for encrypt/decrypt + # swap is true if byte order needs to be reversed + # iv_off is parameter number for the iv + # enc_off is parameter number for the encrypt/decrypt flag + # p1,p2,p3 are the offsets for parameters to be passed to the + # underlying calls. + + &function_begin_B($name,""); + &comment(""); + + $in="esi"; + $out="edi"; + $count="ebp"; + + &push("ebp"); + &push("ebx"); + &push("esi"); + &push("edi"); + + $data_off=4; + $data_off+=4 if ($p1 > 0); + $data_off+=4 if ($p2 > 0); + $data_off+=4 if ($p3 > 0); + + &mov($count, &wparam(2)); # length + + &comment("getting iv ptr from parameter $iv_off"); + &mov("ebx", &wparam($iv_off)); # Get iv ptr + + &mov($in, &DWP(0,"ebx","",0));# iv[0] + &mov($out, &DWP(4,"ebx","",0));# iv[1] + + &push($out); + &push($in); + &push($out); # used in decrypt for iv[1] + &push($in); # used in decrypt for iv[0] + + &mov("ebx", "esp"); # This is the address of tin[2] + + &mov($in, &wparam(0)); # in + &mov($out, &wparam(1)); # out + + # We have loaded them all, how lets push things + &comment("getting encrypt flag from parameter $enc_off"); + &mov("ecx", &wparam($enc_off)); # Get enc flag + if ($p3 > 0) + { + &comment("get and push parameter $p3"); + if ($enc_off != $p3) + { &mov("eax", &wparam($p3)); &push("eax"); } + else { &push("ecx"); } + } + if ($p2 > 0) + { + &comment("get and push parameter $p2"); + if ($enc_off != $p2) + { &mov("eax", &wparam($p2)); &push("eax"); } + else { &push("ecx"); } + } + if ($p1 > 0) + { + &comment("get and push parameter $p1"); + if ($enc_off != $p1) + { &mov("eax", &wparam($p1)); &push("eax"); } + else { &push("ecx"); } + } + &push("ebx"); # push data/iv + + &cmp("ecx",0); + &jz(&label("decrypt")); + + &and($count,0xfffffff8); + &mov("eax", &DWP($data_off,"esp","",0)); # load iv[0] + &mov("ebx", &DWP($data_off+4,"esp","",0)); # load iv[1] + + &jz(&label("encrypt_finish")); + + ############################################################# + + &set_label("encrypt_loop"); + # encrypt start + # "eax" and "ebx" hold iv (or the last cipher text) + + &mov("ecx", &DWP(0,$in,"",0)); # load first 4 bytes + &mov("edx", &DWP(4,$in,"",0)); # second 4 bytes + + &xor("eax", "ecx"); + &xor("ebx", "edx"); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($enc_func); + + &mov("eax", &DWP($data_off,"esp","",0)); + &mov("ebx", &DWP($data_off+4,"esp","",0)); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP(0,$out,"",0),"eax"); + &mov(&DWP(4,$out,"",0),"ebx"); + + # eax and ebx are the next iv. + + &add($in, 8); + &add($out, 8); + + &sub($count, 8); + &jnz(&label("encrypt_loop")); + +###################################################################3 + &set_label("encrypt_finish"); + &mov($count, &wparam(2)); # length + &and($count, 7); + &jz(&label("finish")); + &xor("ecx","ecx"); + &xor("edx","edx"); + &mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4)); + &jmp_ptr($count); + +&set_label("ej7"); + &xor("edx", "edx") if $ppro; # ppro friendly + &movb(&HB("edx"), &BP(6,$in,"",0)); + &shl("edx",8); +&set_label("ej6"); + &movb(&HB("edx"), &BP(5,$in,"",0)); +&set_label("ej5"); + &movb(&LB("edx"), &BP(4,$in,"",0)); +&set_label("ej4"); + &mov("ecx", &DWP(0,$in,"",0)); + &jmp(&label("ejend")); +&set_label("ej3"); + &movb(&HB("ecx"), &BP(2,$in,"",0)); + &xor("ecx", "ecx") if $ppro; # ppro friendly + &shl("ecx",8); +&set_label("ej2"); + &movb(&HB("ecx"), &BP(1,$in,"",0)); +&set_label("ej1"); + &movb(&LB("ecx"), &BP(0,$in,"",0)); +&set_label("ejend"); + + &xor("eax", "ecx"); + &xor("ebx", "edx"); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($enc_func); + + &mov("eax", &DWP($data_off,"esp","",0)); + &mov("ebx", &DWP($data_off+4,"esp","",0)); + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP(0,$out,"",0),"eax"); + &mov(&DWP(4,$out,"",0),"ebx"); + + &jmp(&label("finish")); + + ############################################################# + ############################################################# + &set_label("decrypt",1); + # decrypt start + &and($count,0xfffffff8); + # The next 2 instructions are only for if the jz is taken + &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0] + &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1] + &jz(&label("decrypt_finish")); + + &set_label("decrypt_loop"); + &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes + &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put back + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($dec_func); + + &mov("eax", &DWP($data_off,"esp","",0)); # get return + &mov("ebx", &DWP($data_off+4,"esp","",0)); # + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] + &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] + + &xor("ecx", "eax"); + &xor("edx", "ebx"); + + &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, + &mov("ebx", &DWP(4,$in,"",0)); # next iv actually + + &mov(&DWP(0,$out,"",0),"ecx"); + &mov(&DWP(4,$out,"",0),"edx"); + + &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv + &mov(&DWP($data_off+12,"esp","",0), "ebx"); # + + &add($in, 8); + &add($out, 8); + + &sub($count, 8); + &jnz(&label("decrypt_loop")); +############################ ENDIT #######################3 + &set_label("decrypt_finish"); + &mov($count, &wparam(2)); # length + &and($count, 7); + &jz(&label("finish")); + + &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes + &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov(&DWP($data_off,"esp","",0), "eax"); # put back + &mov(&DWP($data_off+4,"esp","",0), "ebx"); # + + &call($dec_func); + + &mov("eax", &DWP($data_off,"esp","",0)); # get return + &mov("ebx", &DWP($data_off+4,"esp","",0)); # + + &bswap("eax") if $swap; + &bswap("ebx") if $swap; + + &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] + &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] + + &xor("ecx", "eax"); + &xor("edx", "ebx"); + + # this is for when we exit + &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, + &mov("ebx", &DWP(4,$in,"",0)); # next iv actually + +&set_label("dj7"); + &rotr("edx", 16); + &movb(&BP(6,$out,"",0), &LB("edx")); + &shr("edx",16); +&set_label("dj6"); + &movb(&BP(5,$out,"",0), &HB("edx")); +&set_label("dj5"); + &movb(&BP(4,$out,"",0), &LB("edx")); +&set_label("dj4"); + &mov(&DWP(0,$out,"",0), "ecx"); + &jmp(&label("djend")); +&set_label("dj3"); + &rotr("ecx", 16); + &movb(&BP(2,$out,"",0), &LB("ecx")); + &shl("ecx",16); +&set_label("dj2"); + &movb(&BP(1,$in,"",0), &HB("ecx")); +&set_label("dj1"); + &movb(&BP(0,$in,"",0), &LB("ecx")); +&set_label("djend"); + + # final iv is still in eax:ebx + &jmp(&label("finish")); + + +############################ FINISH #######################3 + &set_label("finish",1); + &mov("ecx", &wparam($iv_off)); # Get iv ptr + + ################################################# + $total=16+4; + $total+=4 if ($p1 > 0); + $total+=4 if ($p2 > 0); + $total+=4 if ($p3 > 0); + &add("esp",$total); + + &mov(&DWP(0,"ecx","",0), "eax"); # save iv + &mov(&DWP(4,"ecx","",0), "ebx"); # save iv + + &function_end_A($name); + + &set_label("cbc_enc_jmp_table",1); + &data_word("0"); + &data_word(&label("ej1")); + &data_word(&label("ej2")); + &data_word(&label("ej3")); + &data_word(&label("ej4")); + &data_word(&label("ej5")); + &data_word(&label("ej6")); + &data_word(&label("ej7")); + &set_label("cbc_dec_jmp_table",1); + &data_word("0"); + &data_word(&label("dj1")); + &data_word(&label("dj2")); + &data_word(&label("dj3")); + &data_word(&label("dj4")); + &data_word(&label("dj5")); + &data_word(&label("dj6")); + &data_word(&label("dj7")); + + &function_end_B($name); + + } + +1; diff --git a/3rdparty/des-4.04b/asm/perlasm/readme b/3rdparty/des-4.04b/asm/perlasm/readme new file mode 100644 index 0000000..f02bbee --- /dev/null +++ b/3rdparty/des-4.04b/asm/perlasm/readme @@ -0,0 +1,124 @@ +The perl scripts in this directory are my 'hack' to generate +multiple different assembler formats via the one origional script. + +The way to use this library is to start with adding the path to this directory +and then include it. + +push(@INC,"perlasm","../../perlasm"); +require "x86asm.pl"; + +The first thing we do is setup the file and type of assember + +&asm_init($ARGV[0],$0); + +The first argument is the 'type'. Currently +'cpp', 'sol', 'a.out', 'elf' or 'win32'. +Argument 2 is the file name. + +The reciprocal function is +&asm_finish() which should be called at the end. + +There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler, +and x86unix.pl which is the unix (gas) version. + +Functions of interest are: +&external_label("des_SPtrans"); declare and external variable +&LB(reg); Low byte for a register +&HB(reg); High byte for a register +&BP(off,base,index,scale) Byte pointer addressing +&DWP(off,base,index,scale) Word pointer addressing +&stack_push(num) Basically a 'sub esp, num*4' with extra +&stack_pop(num) inverse of stack_push +&function_begin(name,extra) Start a function with pushing of + edi, esi, ebx and ebp. extra is extra win32 + external info that may be required. +&function_begin_B(name,extra) Same as norma function_begin but no pushing. +&function_end(name) Call at end of function. +&function_end_A(name) Standard pop and ret, for use inside functions +&function_end_B(name) Call at end but with poping or 'ret'. +&swtmp(num) Address on stack temp word. +&wparam(num) Parameter number num, that was push + in C convention. This all works over pushes + and pops. +&comment("hello there") Put in a comment. +&label("loop") Refer to a label, normally a jmp target. +&set_label("loop") Set a label at this point. +&data_word(word) Put in a word of data. + +So how does this all hold together? Given + +int calc(int len, int *data) + { + int i,j=0; + + for (i=0; i"); +&comment(""); + + $filename =~ s/\.pl$//; + &file($filename); + } + +sub asm_finish_cpp + { + return unless $cpp; + + local($tmp,$i); + foreach $i (&get_labels()) + { + $tmp.="#define $i _$i\n"; + } + print <<"EOF"; +/* Run the C pre-processor over this file with one of the following defined + * ELF - elf object files, + * OUT - a.out object files, + * BSDI - BSDI style a.out object files + * SOL - Solaris style elf + */ + +#define TYPE(a,b) .type a,b +#define SIZE(a,b) .size a,b + +#if defined(OUT) || defined(BSDI) +$tmp +#endif + +#ifdef OUT +#define OK 1 +#define ALIGN 4 +#endif + +#ifdef BSDI +#define OK 1 +#define ALIGN 4 +#undef SIZE +#undef TYPE +#endif + +#if defined(ELF) || defined(SOL) +#define OK 1 +#define ALIGN 16 +#endif + +#ifndef OK +You need to define one of +ELF - elf systems - linux-elf, NetBSD and DG-UX +OUT - a.out systems - linux-a.out and FreeBSD +SOL - solaris systems, which are elf with strange comment lines +BSDI - a.out with a very primative version of as. +#endif + +/* Let the Assembler begin :-) */ +EOF + } + +1; diff --git a/3rdparty/des-4.04b/asm/perlasm/x86ms.pl b/3rdparty/des-4.04b/asm/perlasm/x86ms.pl new file mode 100644 index 0000000..3d8e89d --- /dev/null +++ b/3rdparty/des-4.04b/asm/perlasm/x86ms.pl @@ -0,0 +1,345 @@ +#!/usr/local/bin/perl + +package x86ms; + +$label="L000"; + +%lb=( 'eax', 'al', + 'ebx', 'bl', + 'ecx', 'cl', + 'edx', 'dl', + 'ax', 'al', + 'bx', 'bl', + 'cx', 'cl', + 'dx', 'dl', + ); + +%hb=( 'eax', 'ah', + 'ebx', 'bh', + 'ecx', 'ch', + 'edx', 'dh', + 'ax', 'ah', + 'bx', 'bh', + 'cx', 'ch', + 'dx', 'dh', + ); + +sub main'asm_init_output { @out=(); } +sub main'asm_get_output { return(@out); } +sub main'get_labels { return(@labels); } +sub main'external_label { push(@labels,@_); } + +sub main'LB + { + (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; + return($lb{$_[0]}); + } + +sub main'HB + { + (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; + return($hb{$_[0]}); + } + +sub main'BP + { + &get_mem("BYTE",@_); + } + +sub main'DWP + { + &get_mem("DWORD",@_); + } + +sub main'stack_push + { + local($num)=@_; + $stack+=$num*4; + &main'sub("esp",$num*4); + } + +sub main'stack_pop + { + local($num)=@_; + $stack-=$num*4; + &main'add("esp",$num*4); + } + +sub get_mem + { + local($size,$addr,$reg1,$reg2,$idx)=@_; + local($t,$post); + local($ret)="$size PTR "; + + $addr =~ s/^\s+//; + if ($addr =~ /^(.+)\+(.+)$/) + { + $reg2=&conv($1); + $addr="_$2"; + } + elsif ($addr =~ /^[_a-zA-Z]/) + { + $addr="_$addr"; + } + + $reg1="$regs{$reg1}" if defined($regs{$reg1}); + $reg2="$regs{$reg2}" if defined($regs{$reg2}); + if (($addr ne "") && ($addr ne 0)) + { + if ($addr !~ /^-/) + { $ret.=$addr; } + else { $post=$addr; } + } + if ($reg2 ne "") + { + $t=""; + $t="*$idx" if ($idx != 0); + $reg1="+".$reg1 if ("$reg1$post" ne ""); + $ret.="[$reg2$t$reg1$post]"; + } + else + { + $ret.="[$reg1$post]" + } + return($ret); + } + +sub main'mov { &out2("mov",@_); } +sub main'movb { &out2("mov",@_); } +sub main'and { &out2("and",@_); } +sub main'or { &out2("or",@_); } +sub main'shl { &out2("shl",@_); } +sub main'shr { &out2("shr",@_); } +sub main'xor { &out2("xor",@_); } +sub main'xorb { &out2("xor",@_); } +sub main'add { &out2("add",@_); } +sub main'adc { &out2("adc",@_); } +sub main'sub { &out2("sub",@_); } +sub main'rotl { &out2("rol",@_); } +sub main'rotr { &out2("ror",@_); } +sub main'exch { &out2("xchg",@_); } +sub main'cmp { &out2("cmp",@_); } +sub main'lea { &out2("lea",@_); } +sub main'mul { &out1("mul",@_); } +sub main'div { &out1("div",@_); } +sub main'dec { &out1("dec",@_); } +sub main'inc { &out1("inc",@_); } +sub main'jmp { &out1("jmp",@_); } +sub main'jmp_ptr { &out1p("jmp",@_); } +sub main'je { &out1("je",@_); } +sub main'jle { &out1("jle",@_); } +sub main'jz { &out1("jz",@_); } +sub main'jge { &out1("jge",@_); } +sub main'jl { &out1("jl",@_); } +sub main'jb { &out1("jb",@_); } +sub main'jnz { &out1("jnz",@_); } +sub main'jne { &out1("jne",@_); } +sub main'push { &out1("push",@_); $stack+=4; } +sub main'pop { &out1("pop",@_); $stack-=4; } +sub main'bswap { &out1("bswap",@_); &using486(); } +sub main'not { &out1("not",@_); } +sub main'call { &out1("call",'_'.$_[0]); } +sub main'ret { &out0("ret"); } +sub main'nop { &out0("nop"); } + +sub out2 + { + local($name,$p1,$p2)=@_; + local($l,$t); + + push(@out,"\t$name\t"); + $t=&conv($p1).","; + $l=length($t); + push(@out,$t); + $l=4-($l+9)/8; + push(@out,"\t" x $l); + push(@out,&conv($p2)); + push(@out,"\n"); + } + +sub out0 + { + local($name)=@_; + + push(@out,"\t$name\n"); + } + +sub out1 + { + local($name,$p1)=@_; + local($l,$t); + + push(@out,"\t$name\t".&conv($p1)."\n"); + } + +sub conv + { + local($p)=@_; + + $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; + return $p; + } + +sub using486 + { + return if $using486; + $using486++; + grep(s/\.386/\.486/,@out); + } + +sub main'file + { + local($file)=@_; + + local($tmp)=<<"EOF"; + TITLE $file.asm + .386 +.model FLAT +EOF + push(@out,$tmp); + } + +sub main'function_begin + { + local($func,$extra)=@_; + + push(@labels,$func); + + local($tmp)=<<"EOF"; +_TEXT SEGMENT +PUBLIC _$func +$extra +_$func PROC NEAR + push ebp + push ebx + push esi + push edi +EOF + push(@out,$tmp); + $stack=20; + } + +sub main'function_begin_B + { + local($func,$extra)=@_; + + local($tmp)=<<"EOF"; +_TEXT SEGMENT +PUBLIC _$func +$extra +_$func PROC NEAR +EOF + push(@out,$tmp); + $stack=4; + } + +sub main'function_end + { + local($func)=@_; + + local($tmp)=<<"EOF"; + pop edi + pop esi + pop ebx + pop ebp + ret +_$func ENDP +_TEXT ENDS +EOF + push(@out,$tmp); + $stack=0; + %label=(); + } + +sub main'function_end_B + { + local($func)=@_; + + local($tmp)=<<"EOF"; +_$func ENDP +_TEXT ENDS +EOF + push(@out,$tmp); + $stack=0; + %label=(); + } + +sub main'function_end_A + { + local($func)=@_; + + local($tmp)=<<"EOF"; + pop edi + pop esi + pop ebx + pop ebp + ret +EOF + push(@out,$tmp); + } + +sub main'file_end + { + push(@out,"END\n"); + } + +sub main'wparam + { + local($num)=@_; + + return(&main'DWP($stack+$num*4,"esp","",0)); + } + +sub main'swtmp + { + return(&main'DWP($_[0]*4,"esp","",0)); + } + +# Should use swtmp, which is above esp. Linix can trash the stack above esp +#sub main'wtmp +# { +# local($num)=@_; +# +# return(&main'DWP(-(($num+1)*4),"esp","",0)); +# } + +sub main'comment + { + foreach (@_) + { + push(@out,"\t; $_\n"); + } + } + +sub main'label + { + if (!defined($label{$_[0]})) + { + $label{$_[0]}="\$${label}${_[0]}"; + $label++; + } + return($label{$_[0]}); + } + +sub main'set_label + { + if (!defined($label{$_[0]})) + { + $label{$_[0]}="${label}${_[0]}"; + $label++; + } + push(@out,"$label{$_[0]}:\n"); + } + +sub main'data_word + { + push(@out,"\tDD\t$_[0]\n"); + } + +sub out1p + { + local($name,$p1)=@_; + local($l,$t); + + push(@out,"\t$name\t ".&conv($p1)."\n"); + } diff --git a/3rdparty/des-4.04b/asm/perlasm/x86unix.pl b/3rdparty/des-4.04b/asm/perlasm/x86unix.pl new file mode 100644 index 0000000..b25780d --- /dev/null +++ b/3rdparty/des-4.04b/asm/perlasm/x86unix.pl @@ -0,0 +1,403 @@ +#!/usr/local/bin/perl + +package x86unix; + +$label="L000"; + +$align=($main'aout)?"4":"16"; +$under=($main'aout)?"_":""; +$com_start=($main'sol)?"/":"#"; + +sub main'asm_init_output { @out=(); } +sub main'asm_get_output { return(@out); } +sub main'get_labels { return(@labels); } +sub main'external_label { push(@labels,@_); } + +if ($main'cpp) + { + $align="ALIGN"; + $under=""; + $com_start='/*'; + $com_end='*/'; + } + +%lb=( 'eax', '%al', + 'ebx', '%bl', + 'ecx', '%cl', + 'edx', '%dl', + 'ax', '%al', + 'bx', '%bl', + 'cx', '%cl', + 'dx', '%dl', + ); + +%hb=( 'eax', '%ah', + 'ebx', '%bh', + 'ecx', '%ch', + 'edx', '%dh', + 'ax', '%ah', + 'bx', '%bh', + 'cx', '%ch', + 'dx', '%dh', + ); + +%regs=( 'eax', '%eax', + 'ebx', '%ebx', + 'ecx', '%ecx', + 'edx', '%edx', + 'esi', '%esi', + 'edi', '%edi', + 'ebp', '%ebp', + 'esp', '%esp', + ); + +%reg_val=( + 'eax', 0x00, + 'ebx', 0x03, + 'ecx', 0x01, + 'edx', 0x02, + 'esi', 0x06, + 'edi', 0x07, + 'ebp', 0x05, + 'esp', 0x04, + ); + +sub main'LB + { + (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; + return($lb{$_[0]}); + } + +sub main'HB + { + (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; + return($hb{$_[0]}); + } + +sub main'DWP + { + local($addr,$reg1,$reg2,$idx)=@_; + + $ret=""; + $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/; + $reg1="$regs{$reg1}" if defined($regs{$reg1}); + $reg2="$regs{$reg2}" if defined($regs{$reg2}); + $ret.=$addr if ($addr ne "") && ($addr ne 0); + if ($reg2 ne "") + { $ret.="($reg1,$reg2,$idx)"; } + else + { $ret.="($reg1)" } + return($ret); + } + +sub main'BP + { + return(&main'DWP(@_)); + } + +#sub main'BP +# { +# local($addr,$reg1,$reg2,$idx)=@_; +# +# $ret=""; +# +# $addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/; +# $reg1="$regs{$reg1}" if defined($regs{$reg1}); +# $reg2="$regs{$reg2}" if defined($regs{$reg2}); +# $ret.=$addr if ($addr ne "") && ($addr ne 0); +# if ($reg2 ne "") +# { $ret.="($reg1,$reg2,$idx)"; } +# else +# { $ret.="($reg1)" } +# return($ret); +# } + +sub main'mov { &out2("movl",@_); } +sub main'movb { &out2("movb",@_); } +sub main'and { &out2("andl",@_); } +sub main'or { &out2("orl",@_); } +sub main'shl { &out2("sall",@_); } +sub main'shr { &out2("shrl",@_); } +sub main'xor { &out2("xorl",@_); } +sub main'xorb { &out2("xorb",@_); } +sub main'add { &out2("addl",@_); } +sub main'adc { &out2("adcl",@_); } +sub main'sub { &out2("subl",@_); } +sub main'rotl { &out2("roll",@_); } +sub main'rotr { &out2("rorl",@_); } +sub main'exch { &out2("xchg",@_); } +sub main'cmp { &out2("cmpl",@_); } +sub main'lea { &out2("leal",@_); } +sub main'mul { &out1("mull",@_); } +sub main'div { &out1("divl",@_); } +sub main'jmp { &out1("jmp",@_); } +sub main'jmp_ptr { &out1p("jmp",@_); } +sub main'je { &out1("je",@_); } +sub main'jle { &out1("jle",@_); } +sub main'jne { &out1("jne",@_); } +sub main'jnz { &out1("jnz",@_); } +sub main'jz { &out1("jz",@_); } +sub main'jge { &out1("jge",@_); } +sub main'jl { &out1("jl",@_); } +sub main'jb { &out1("jb",@_); } +sub main'dec { &out1("decl",@_); } +sub main'inc { &out1("incl",@_); } +sub main'push { &out1("pushl",@_); $stack+=4; } +sub main'pop { &out1("popl",@_); $stack-=4; } +sub main'bswap { &out1("bswapl",@_); } +sub main'not { &out1("notl",@_); } +sub main'call { &out1("call",$under.$_[0]); } +sub main'ret { &out0("ret"); } +sub main'nop { &out0("nop"); } + +sub out2 + { + local($name,$p1,$p2)=@_; + local($l,$ll,$t); + local(%special)=( "roll",0xD1C0,"rorl",0xD1C8, + "rcll",0xD1D0,"rcrl",0xD1D8, + "shll",0xD1E0,"shrl",0xD1E8, + "sarl",0xD1F8); + + if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1)) + { + $op=$special{$name}|$reg_val{$p1}; + $tmp1=sprintf ".byte %d\n",($op>>8)&0xff; + $tmp2=sprintf ".byte %d\t",$op &0xff; + push(@out,$tmp1); + push(@out,$tmp2); + + $p2=&conv($p2); + $p1=&conv($p1); + &main'comment("$name $p2 $p1"); + return; + } + + push(@out,"\t$name\t"); + $t=&conv($p2).","; + $l=length($t); + push(@out,$t); + $ll=4-($l+9)/8; + $tmp1=sprintf "\t" x $ll; + push(@out,$tmp1); + push(@out,&conv($p1)."\n"); + } + +sub out1 + { + local($name,$p1)=@_; + local($l,$t); + + push(@out,"\t$name\t".&conv($p1)."\n"); + } + +sub out1p + { + local($name,$p1)=@_; + local($l,$t); + + push(@out,"\t$name\t*".&conv($p1)."\n"); + } + +sub out0 + { + push(@out,"\t$_[0]\n"); + } + +sub conv + { + local($p)=@_; + +# $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; + + $p=$regs{$p} if (defined($regs{$p})); + + $p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/; + $p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/; + return $p; + } + +sub main'file + { + local($file)=@_; + + local($tmp)=<<"EOF"; + .file "$file.s" + .version "01.01" +gcc2_compiled.: +EOF + push(@out,$tmp); + } + +sub main'function_begin + { + local($func)=@_; + + $func=$under.$func; + + local($tmp)=<<"EOF"; +.text + .align $align +.globl $func +EOF + push(@out,$tmp); + if ($main'cpp) + { $tmp=push(@out,"\tTYPE($func,\@function)\n"); } + else { $tmp=push(@out,"\t.type\t$func,\@function\n"); } + push(@out,"$func:\n"); + $tmp=<<"EOF"; + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + +EOF + push(@out,$tmp); + $stack=20; + } + +sub main'function_begin_B + { + local($func,$extra)=@_; + + $func=$under.$func; + + local($tmp)=<<"EOF"; +.text + .align $align +.globl $func +EOF + push(@out,$tmp); + if ($main'cpp) + { push(@out,"\tTYPE($func,\@function)\n"); } + else { push(@out,"\t.type $func,\@function\n"); } + push(@out,"$func:\n"); + $stack=4; + } + +sub main'function_end + { + local($func)=@_; + + $func=$under.$func; + + local($tmp)=<<"EOF"; + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +.${func}_end: +EOF + push(@out,$tmp); + if ($main'cpp) + { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); } + else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); } + push(@out,".ident \"$func\"\n"); + $stack=0; + %label=(); + } + +sub main'function_end_A + { + local($func)=@_; + + local($tmp)=<<"EOF"; + popl %edi + popl %esi + popl %ebx + popl %ebp + ret +EOF + push(@out,$tmp); + } + +sub main'function_end_B + { + local($func)=@_; + + $func=$under.$func; + + push(@out,".${func}_end:\n"); + if ($main'cpp) + { push(@out,"\tSIZE($func,.${func}_end-$func)\n"); } + else { push(@out,"\t.size\t$func,.${func}_end-$func\n"); } + push(@out,".ident \"desasm.pl\"\n"); + $stack=0; + %label=(); + } + +sub main'wparam + { + local($num)=@_; + + return(&main'DWP($stack+$num*4,"esp","",0)); + } + +sub main'stack_push + { + local($num)=@_; + $stack+=$num*4; + &main'sub("esp",$num*4); + } + +sub main'stack_pop + { + local($num)=@_; + $stack-=$num*4; + &main'add("esp",$num*4); + } + +sub main'swtmp + { + return(&main'DWP($_[0]*4,"esp","",0)); + } + +# Should use swtmp, which is above esp. Linix can trash the stack above esp +#sub main'wtmp +# { +# local($num)=@_; +# +# return(&main'DWP(-($num+1)*4,"esp","",0)); +# } + +sub main'comment + { + foreach (@_) + { + if (/^\s*$/) + { push(@out,"\n"); } + else + { push(@out,"\t$com_start $_ $com_end\n"); } + } + } + +sub main'label + { + if (!defined($label{$_[0]})) + { + $label{$_[0]}=".${label}${_[0]}"; + $label++; + } + return($label{$_[0]}); + } + +sub main'set_label + { + if (!defined($label{$_[0]})) + { + $label{$_[0]}=".${label}${_[0]}"; + $label++; + } + push(@out,".align $align\n") if ($_[1] != 0); + push(@out,"$label{$_[0]}:\n"); + } + +sub main'file_end + { + } + +sub main'data_word + { + push(@out,"\t.long $_[0]\n"); + } -- cgit v1.2.3