7 $::lbdecor
="\$L"; # local label decoration
8 $nmdecor="_"; # external name decoration
14 { my ($opcode,@arg)=@_;
16 # fix hexadecimal constants
17 for (@arg) { s/(?<![\w\$\.])0x([0-9a-f]+)/0$1h/oi; }
19 if ($opcode !~ /movq/)
20 { # fix xmm references
21 $arg[0] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[1]=~/\bxmm[0-7]\b/i);
22 $arg[1] =~ s/\b[A-Z]+WORD\s+PTR/XMMWORD PTR/i if ($arg[0]=~/\bxmm[0-7]\b/i);
25 &::emit
($opcode,@arg);
29 # opcodes not covered by ::generic above, mostly inconsistent namings...
31 sub ::call
{ &::emit
("call",(&::islabel
($_[0]) or "$nmdecor$_[0]")); }
32 sub ::call_ptr
{ &::emit
("call",@_); }
33 sub ::jmp_ptr
{ &::emit
("jmp",@_); }
34 sub ::lock { &::data_byte
(0xf0); }
37 { my($size,$addr,$reg1,$reg2,$idx)=@_;
40 $ret .= "$size PTR " if ($size ne "");
43 # prepend global references with optional underscore
44 $addr =~ s/^([^\+\-0-9][^\+\-]*)/&::islabel($1) or "$nmdecor$1"/ige;
45 # put address arithmetic expression in parenthesis
46 $addr="($addr)" if ($addr =~ /^.+[\-\+].+$/);
48 if (($addr ne "") && ($addr ne 0))
49 { if ($addr !~ /^-/) { $ret .= "$addr"; }
57 $ret .= "+$reg1" if ($reg1 ne "");
63 $ret =~ s/\+\]/]/; # in case $addr was the only argument
68 sub ::BP
{ &get_mem
("BYTE",@_); }
69 sub ::WP
{ &get_mem
("WORD",@_); }
70 sub ::DWP
{ &get_mem
("DWORD",@_); }
71 sub ::QWP
{ &get_mem
("QWORD",@_); }
79 ECHO MASM version
8.00 or later is strongly recommended
.
85 .text\
$ SEGMENT PAGE
'CODE'
87 .text\
$ SEGMENT ALIGN
(64) 'CODE'
94 sub ::function_begin_B
96 my $global=($func !~ /^_/);
97 my $begin="${::lbdecor}_${func}_begin";
99 &::LABEL
($func,$global?
"$begin":"$nmdecor$func");
100 $func="ALIGN\t16\n".$nmdecor.$func."\tPROC";
102 if ($global) { $func.=" PUBLIC\n${begin}::\n"; }
103 else { $func.=" PRIVATE\n"; }
110 push(@out,"$nmdecor$func ENDP\n");
116 { my $xmmheader=<<___
;
125 if (grep {/\b[x]?mm[0-7]\b/i} @out) {
126 grep {s/\.[3-7]86/$xmmheader/} @out;
129 push(@out,"$segment ENDS\n");
131 if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out)
134 COMM
${nmdecor
}OPENSSL_ia32cap_P
:QWORD
137 # comment out OPENSSL_ia32cap_P declarations
138 grep {s/(^EXTERN\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out;
141 push (@out,$initseg) if ($initseg);
145 sub ::comment
{ foreach (@_) { push(@out,"\t; $_\n"); } }
148 { my $l=shift; push(@out,$l.($l=~/^\Q${::lbdecor}\E[0-9]{3}/?
":\n":"::\n")); };
152 { push(@out, "EXTERN\t".&::LABEL
($_,$nmdecor.$_).":NEAR\n"); }
156 { push(@out,"PUBLIC\t".&::LABEL
($_[0],$nmdecor.$_[0])."\n"); }
159 { push(@out,("DB\t").join(',',@_)."\n"); }
162 { push(@out,("DW\t").join(',',@_)."\n"); }
165 { push(@out,("DD\t").join(',',@_)."\n"); }
168 { push(@out,"ALIGN\t$_[0]\n"); }
172 &::lea
($dst,&::DWP
($sym));
176 { my $f=$nmdecor.shift;
179 .CRT\
$XCU SEGMENT DWORD PUBLIC
'DATA'
187 { push(@out,"$segment\tENDS\n_DATA\tSEGMENT\n"); $segment="_DATA"; }
191 push(@out,"IF \@Version GE 710\n");
192 push(@out,".SAFESEH ".&::LABEL
($nm,$nmdecor.$nm)."\n");
193 push(@out,"ENDIF\n");