1#!/usr/local/bin/perl 2 3package x86ms; 4 5$label="L000"; 6 7%lb=( 'eax', 'al', 8 'ebx', 'bl', 9 'ecx', 'cl', 10 'edx', 'dl', 11 'ax', 'al', 12 'bx', 'bl', 13 'cx', 'cl', 14 'dx', 'dl', 15 ); 16 17%hb=( 'eax', 'ah', 18 'ebx', 'bh', 19 'ecx', 'ch', 20 'edx', 'dh', 21 'ax', 'ah', 22 'bx', 'bh', 23 'cx', 'ch', 24 'dx', 'dh', 25 ); 26 27sub main'asm_init_output { @out=(); } 28sub main'asm_get_output { return(@out); } 29sub main'get_labels { return(@labels); } 30sub main'external_label { push(@labels,@_); } 31 32sub main'LB 33 { 34 (defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n"; 35 return($lb{$_[0]}); 36 } 37 38sub main'HB 39 { 40 (defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n"; 41 return($hb{$_[0]}); 42 } 43 44sub main'BP 45 { 46 &get_mem("BYTE",@_); 47 } 48 49sub main'DWP 50 { 51 &get_mem("DWORD",@_); 52 } 53 54sub main'QWP 55 { 56 &get_mem("QWORD",@_); 57 } 58 59sub main'BC 60 { 61 return @_; 62 } 63 64sub main'DWC 65 { 66 return @_; 67 } 68 69sub main'stack_push 70 { 71 local($num)=@_; 72 $stack+=$num*4; 73 &main'sub("esp",$num*4); 74 } 75 76sub main'stack_pop 77 { 78 local($num)=@_; 79 $stack-=$num*4; 80 &main'add("esp",$num*4); 81 } 82 83sub get_mem 84 { 85 local($size,$addr,$reg1,$reg2,$idx)=@_; 86 local($t,$post); 87 local($ret)="$size PTR "; 88 89 $addr =~ s/^\s+//; 90 if ($addr =~ /^(.+)\+(.+)$/) 91 { 92 $reg2=&conv($1); 93 $addr="_$2"; 94 } 95 elsif ($addr =~ /^[_a-z][_a-z0-9]*$/i) 96 { 97 $addr="_$addr"; 98 } 99 100 if ($addr =~ /^.+\-.+$/) { $addr="($addr)"; } 101 102 $reg1="$regs{$reg1}" if defined($regs{$reg1}); 103 $reg2="$regs{$reg2}" if defined($regs{$reg2}); 104 if (($addr ne "") && ($addr ne 0)) 105 { 106 if ($addr !~ /^-/) 107 { $ret.=$addr; } 108 else { $post=$addr; } 109 } 110 if ($reg2 ne "") 111 { 112 $t=""; 113 $t="*$idx" if ($idx != 0); 114 $reg1="+".$reg1 if ("$reg1$post" ne ""); 115 $ret.="[$reg2$t$reg1$post]"; 116 } 117 else 118 { 119 $ret.="[$reg1$post]" 120 } 121 $ret =~ s/\[\]//; # in case $addr was the only argument 122 return($ret); 123 } 124 125sub main'mov { &out2("mov",@_); } 126sub main'movb { &out2("mov",@_); } 127sub main'and { &out2("and",@_); } 128sub main'or { &out2("or",@_); } 129sub main'shl { &out2("shl",@_); } 130sub main'shr { &out2("shr",@_); } 131sub main'xor { &out2("xor",@_); } 132sub main'xorb { &out2("xor",@_); } 133sub main'add { &out2("add",@_); } 134sub main'adc { &out2("adc",@_); } 135sub main'sub { &out2("sub",@_); } 136sub main'sbb { &out2("sbb",@_); } 137sub main'rotl { &out2("rol",@_); } 138sub main'rotr { &out2("ror",@_); } 139sub main'exch { &out2("xchg",@_); } 140sub main'cmp { &out2("cmp",@_); } 141sub main'lea { &out2("lea",@_); } 142sub main'mul { &out1("mul",@_); } 143sub main'div { &out1("div",@_); } 144sub main'dec { &out1("dec",@_); } 145sub main'inc { &out1("inc",@_); } 146sub main'jmp { &out1("jmp",@_); } 147sub main'jmp_ptr { &out1p("jmp",@_); } 148sub main'je { &out1("je",@_); } 149sub main'jle { &out1("jle",@_); } 150sub main'jz { &out1("jz",@_); } 151sub main'jge { &out1("jge",@_); } 152sub main'jl { &out1("jl",@_); } 153sub main'ja { &out1("ja",@_); } 154sub main'jae { &out1("jae",@_); } 155sub main'jb { &out1("jb",@_); } 156sub main'jbe { &out1("jbe",@_); } 157sub main'jc { &out1("jc",@_); } 158sub main'jnc { &out1("jnc",@_); } 159sub main'jnz { &out1("jnz",@_); } 160sub main'jne { &out1("jne",@_); } 161sub main'jno { &out1("jno",@_); } 162sub main'push { &out1("push",@_); $stack+=4; } 163sub main'pop { &out1("pop",@_); $stack-=4; } 164sub main'pushf { &out0("pushfd"); $stack+=4; } 165sub main'popf { &out0("popfd"); $stack-=4; } 166sub main'bswap { &out1("bswap",@_); &using486(); } 167sub main'not { &out1("not",@_); } 168sub main'call { &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); } 169sub main'ret { &out0("ret"); } 170sub main'nop { &out0("nop"); } 171sub main'test { &out2("test",@_); } 172sub main'bt { &out2("bt",@_); } 173sub main'leave { &out0("leave"); } 174sub main'cpuid { &out0("DW\t0A20Fh"); } 175sub main'rdtsc { &out0("DW\t0310Fh"); } 176sub main'halt { &out0("hlt"); } 177sub main'movz { &out2("movzx",@_); } 178sub main'neg { &out1("neg",@_); } 179sub main'cld { &out0("cld"); } 180 181# SSE2 182sub main'emms { &out0("emms"); } 183sub main'movd { &out2("movd",@_); } 184sub main'movq { &out2("movq",@_); } 185sub main'movdqu { &out2("movdqu",@_); } 186sub main'movdqa { &out2("movdqa",@_); } 187sub main'movdq2q{ &out2("movdq2q",@_); } 188sub main'movq2dq{ &out2("movq2dq",@_); } 189sub main'paddq { &out2("paddq",@_); } 190sub main'pmuludq{ &out2("pmuludq",@_); } 191sub main'psrlq { &out2("psrlq",@_); } 192sub main'psllq { &out2("psllq",@_); } 193sub main'pxor { &out2("pxor",@_); } 194sub main'por { &out2("por",@_); } 195sub main'pand { &out2("pand",@_); } 196 197sub out2 198 { 199 local($name,$p1,$p2)=@_; 200 local($l,$t); 201 202 push(@out,"\t$name\t"); 203 $t=&conv($p1).","; 204 $l=length($t); 205 push(@out,$t); 206 $l=4-($l+9)/8; 207 push(@out,"\t" x $l); 208 push(@out,&conv($p2)); 209 push(@out,"\n"); 210 } 211 212sub out0 213 { 214 local($name)=@_; 215 216 push(@out,"\t$name\n"); 217 } 218 219sub out1 220 { 221 local($name,$p1)=@_; 222 local($l,$t); 223 224 push(@out,"\t$name\t".&conv($p1)."\n"); 225 } 226 227sub conv 228 { 229 local($p)=@_; 230 231 $p =~ s/0x([0-9A-Fa-f]+)/0$1h/; 232 return $p; 233 } 234 235sub using486 236 { 237 return if $using486; 238 $using486++; 239 grep(s/\.386/\.486/,@out); 240 } 241 242sub main'file 243 { 244 local($file)=@_; 245 246 local($tmp)=<<"EOF"; 247 TITLE $file.asm 248 .386 249.model FLAT 250EOF 251 push(@out,$tmp); 252 } 253 254sub main'function_begin 255 { 256 local($func,$extra)=@_; 257 258 push(@labels,$func); 259 260 local($tmp)=<<"EOF"; 261_TEXT\$ SEGMENT PAGE 'CODE' 262PUBLIC _$func 263$extra 264_$func PROC NEAR 265 push ebp 266 push ebx 267 push esi 268 push edi 269EOF 270 push(@out,$tmp); 271 $stack=20; 272 } 273 274sub main'function_begin_B 275 { 276 local($func,$extra)=@_; 277 278 local($tmp)=<<"EOF"; 279_TEXT\$ SEGMENT PAGE 'CODE' 280PUBLIC _$func 281$extra 282_$func PROC NEAR 283EOF 284 push(@out,$tmp); 285 $stack=4; 286 } 287 288sub main'function_end 289 { 290 local($func)=@_; 291 292 local($tmp)=<<"EOF"; 293 pop edi 294 pop esi 295 pop ebx 296 pop ebp 297 ret 298_$func ENDP 299_TEXT\$ ENDS 300EOF 301 push(@out,$tmp); 302 $stack=0; 303 %label=(); 304 } 305 306sub main'function_end_B 307 { 308 local($func)=@_; 309 310 local($tmp)=<<"EOF"; 311_$func ENDP 312_TEXT\$ ENDS 313EOF 314 push(@out,$tmp); 315 $stack=0; 316 %label=(); 317 } 318 319sub main'function_end_A 320 { 321 local($func)=@_; 322 323 local($tmp)=<<"EOF"; 324 pop edi 325 pop esi 326 pop ebx 327 pop ebp 328 ret 329EOF 330 push(@out,$tmp); 331 } 332 333sub main'file_end 334 { 335 # try to detect if SSE2 or MMX extensions were used... 336 if (grep {/xmm[0-7]\s*,/i} @out) { 337 grep {s/\.[3-7]86/\.686\n\t\.XMM/} @out; 338 } 339 elsif (grep {/mm[0-7]\s*,/i} @out) { 340 grep {s/\.[3-7]86/\.686\n\t\.MMX/} @out; 341 } 342 push(@out,"END\n"); 343 } 344 345sub main'wparam 346 { 347 local($num)=@_; 348 349 return(&main'DWP($stack+$num*4,"esp","",0)); 350 } 351 352sub main'swtmp 353 { 354 return(&main'DWP($_[0]*4,"esp","",0)); 355 } 356 357# Should use swtmp, which is above esp. Linix can trash the stack above esp 358#sub main'wtmp 359# { 360# local($num)=@_; 361# 362# return(&main'DWP(-(($num+1)*4),"esp","",0)); 363# } 364 365sub main'comment 366 { 367 foreach (@_) 368 { 369 push(@out,"\t; $_\n"); 370 } 371 } 372 373sub main'public_label 374 { 375 $label{$_[0]}="_$_[0]" if (!defined($label{$_[0]})); 376 push(@out,"PUBLIC\t$label{$_[0]}\n"); 377 } 378 379sub main'label 380 { 381 if (!defined($label{$_[0]})) 382 { 383 $label{$_[0]}="\$${label}${_[0]}"; 384 $label++; 385 } 386 return($label{$_[0]}); 387 } 388 389sub main'set_label 390 { 391 if (!defined($label{$_[0]})) 392 { 393 $label{$_[0]}="\$${label}${_[0]}"; 394 $label++; 395 } 396 if ($_[1]!=0 && $_[1]>1) 397 { 398 main'align($_[1]); 399 } 400 if((defined $_[2]) && ($_[2] == 1)) 401 { 402 push(@out,"$label{$_[0]}::\n"); 403 } 404 elsif ($label{$_[0]} !~ /^\$/) 405 { 406 push(@out,"$label{$_[0]}\tLABEL PTR\n"); 407 } 408 else 409 { 410 push(@out,"$label{$_[0]}:\n"); 411 } 412 } 413 414sub main'data_word 415 { 416 push(@out,"\tDD\t".join(',',@_)."\n"); 417 } 418 419sub main'align 420 { 421 push(@out,"\tALIGN\t$_[0]\n"); 422 } 423 424sub out1p 425 { 426 local($name,$p1)=@_; 427 local($l,$t); 428 429 push(@out,"\t$name\t ".&conv($p1)."\n"); 430 } 431 432sub main'picmeup 433 { 434 local($dst,$sym)=@_; 435 &main'lea($dst,&main'DWP($sym)); 436 } 437 438sub main'blindpop { &out1("pop",@_); } 439 440sub main'initseg 441 { 442 local($f)=@_; 443 local($tmp)=<<___; 444OPTION DOTNAME 445.CRT\$XIU SEGMENT DWORD PUBLIC 'DATA' 446EXTRN _$f:NEAR 447DD _$f 448.CRT\$XIU ENDS 449___ 450 push(@out,$tmp); 451 } 452 4531; 454