📄 gas2intel
字号:
#!/usr/bin/perl
#
# gas2intel Copyright (C) 1999 Mark H. Weaver <mhw@netris.org>
#
# This script converts a subset of AT&T-style x86 assembly, which
# gas uses, into Intel-style. It is far from complete, but is just
# good enough to convert the asm files it is currently needed for.
#
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# $Id: gas2intel,v 1.8 1999/04/29 21:23:00 mhw Exp $
#
use Getopt::Std;
$re_sym = "[A-Za-z_.][A-Za-z0-9_.]*";
%size_prefix = (
"" => "",
"b" => "BYTE PTR ",
"w" => "WORD PTR ",
"l" => "DWORD PTR ",
"q" => "QWORD PTR " # XXX Just a guess, may be wrong
);
sub fatal {
print STDERR @_;
exit (1);
}
sub lerr {
&fatal ("Line $.: @_");
}
sub translate_sym {
my $sym = $_[0];
if (!defined ($sym_table{$sym})) {
$sym =~ s/^([A-Za-z_])/_$1/ if (!$inline);
$sym =~ s/^\.//;
}
return $sym;
}
sub comment {
my $str = $_[0];
if ($inline && $proclabel eq "") {
if ($str =~ /\S/) {
return "/*$str */\n";
} else {
return "\n";
}
} else {
return ";$str\n";
}
}
sub start_repeat {
my ($type, $count) = @_;
push (@nested_repeat_bufs, $repeat_buf);
push (@nested_repeat_counts, $repeat_count);
push (@nested_repeat_starts, $repeat_start);
push (@nested_repeat_types, $repeat_type);
$repeat_buf = "";
$repeat_count = $count;
$repeat_start = $.;
$repeat_type = $type;
}
sub end_repeat {
my $type = $_[0];
if ($repeat_type ne $type) {
if ($repeat_type eq "main") {
&fatal ("Line $.: No matching $type\n");
} else {
&fatal ("Line $repeat_start: Unterminated $repeat_type\n");
}
}
$repeat_buf = pop (@nested_repeat_bufs) . ($repeat_buf x $repeat_count);
$repeat_count = pop (@nested_repeat_counts);
$repeat_start = pop (@nested_repeat_starts);
$repeat_type = pop (@nested_repeat_types);
}
sub append_line {
$repeat_buf .= $leader . $label . $_ . $trailer;
}
getopts ('i', \%opts);
$inline = $opts{'i'};
print &comment (" ***************************************************");
print &comment (" ************ DO NOT EDIT THIS FILE!!!! ************");
print &comment (" ***************************************************");
print &comment (" This file was automatically generated by gas2intel.");
print &comment (" Edit the original gas version instead.");
print "\n";
&start_repeat ("main", 1);
while (<>) {
chomp; # Strip trailing newline
s/\s+$//; # Strip trailing whitespace
if (s/#\%!// && !$inline) {
next;
}
if (s/#;//) { # This is for commenting out instructions
$leader = ";"; # which should still be translated.
} else {
$leader = "";
}
if (s/(\s*)#(.*)$//) { # Move comment to another variable
$comment = $2;
$trailer = $1 . &comment ($comment);
if ($comment =~ s/\$Id:/Generated from Id:/) {
$trailer .= &comment ($comment);
}
} else {
$comment = "";
$trailer = "\n";
}
if (s/^(\s*)//) { # Move leading space to another var
$leader .= $1;
}
if (!$header_done && ($_ ne "" || $comment =~ /^\%\% \S+/)) {
if (!$inline) {
$leader = ".386\n" .
";FLAT\tgroup _TEXT\n" .
";\tassume cs:FLAT, ds:FLAT, ss:FLAT\n" .
"_TEXT\tsegment para public use32 'CODE'\n\n" .
$leader;
}
$header_done = 1;
}
if (s/^($re_sym:\s*)//) { # Move label to another variable
$label = &translate_sym ($1);
} else {
$label = "";
}
if ($_ eq "" && $comment =~ /^\%\% (\S+)(\s+(.*))?$/) {
$_ = $1;
$argstr = $2;
@args = split (/\s*,\s*/, $3);
$argstr =~ s/^\s//;
tr/A-Z/a-z/;
$trailer = "\n";
if (/^proc$/) {
&lerr ("Wrong # of args\n") if ($#args != -1);
&fatal ("Line $procstart: Missing endp\n") if ($proclabel ne "");
$proclabel = $label;
$label = "";
$proclabel =~ s/:.*//;
$procstart = $.;
if ($inline) {
$_ = "__asm {";
} else {
$_ = "$proclabel proc near";
}
} elsif (/^endp$/) {
&lerr ("Wrong # of args\n") if ($#args != -1);
&lerr ("No matching proc\n") if ($proclabel eq "");
if ($inline) {
$_ = " }";
} else {
$_ = "$proclabel endp";
}
$proclabel = "";
} elsif (/^extern$/) {
&lerr ("Wrong # of args\n") if ($#args != 1);
next if ($inline);
$sym = &translate_sym (@args[0]);
$type = @args[1];
$_ = "extern $sym:$type";
} elsif (/^!$/) {
next if (!$inline);
$_ = $argstr;
} elsif (/^if-not-inline$/) {
&start_repeat ("if-not-inline", !$inline);
next;
} elsif (/^end-not-inline$/) {
&end_repeat ("if-not-inline");
next;
} else {
&lerr ("Unrecognized special comment\n");
}
} elsif ($_ eq "") { # Blank line, no translation
} elsif (/^\.globa?l\s+($re_sym)$/) {
my $sym = &translate_sym ($1);
next if ($inline);
$_ = "public $sym";
} elsif (/^\.align\s+([0-9]+)$/) {
$_ = "align $1";
} elsif (/^\.equ\s+($re_sym)\s*,\s*(.*)$/) {
my ($sym,$val) = ($1,$2);
$sym_table{$sym} = $val;
if ($inline) {
$leader = "";
$_ = "#define $sym $val";
} else {
$_ = "$sym EQU $val"; # Just a guess
}
} elsif (/^\.rept\s+([0-9]+)$/) {
$_ = "; REPEAT $1";
&append_line;
&start_repeat (".rept", $1);
next;
} elsif (/^\.endr$/) {
$repeat_buf .= ";--\n";
&end_repeat (".rept");
$_ = "; END REPEAT";
} elsif (/^\./) {
&fatal ("Unrecognized directive: $_\n");
} elsif (/^([A-Za-z]+)(\s+(.*))?$/) {
$op = $1;
$_ = $2;
$_ = "," . $_ if $_ ne "";
@args = ();
# XXX: Too simplistic for char consts
while (s/^\s*,\s*([^,(]*(\([^)]+\))?)\s*//) {
push (@args, $1);
}
&lerr ("Invalid argument syntax\n") if $_ ne "";
$_ = $op;
tr/A-Z/a-z/; # Convert opcode to all lowercase
$size = "";
if (/^(ret|pushad|popad|fld[z1])$/) {
# zero-arity instructions
&lerr ("Wrong # of args\n") if ($#args != -1);
$op = $1;
} elsif (/^(push|pop|inc|dec|neg|not)([bwlq])$/) {
# unary int instructions
&lerr ("Wrong # of args\n") if ($#args != 0);
$op = $1;
$size = $2;
} elsif (/^(lea|cmp|ad[dc]|s[ub]b|i?mul|i?div|and|or|xor|r[oc][lr]|s[ha][lr]|mov)([bwlq])$/) {
# binary int instructions
&lerr ("Wrong # of args\n") if ($#args != 1);
$op = $1;
$size = $2;
@args = ($args[1], $args[0]); # Swap args
} elsif (/^(test)$/) {
# sizeless binary int instructions
&lerr ("Wrong # of args\n") if ($#args != 1);
$op = $1;
@args = ($args[1], $args[0]); # Swap args
} elsif (/^(fild|fistp?)([slq])$/) {
# unary float-int instructions
&lerr ("Wrong # of args\n") if ($#args != 0);
$op = $1;
$size = $2;
$size =~ tr/s/w/;
} elsif (/^(fld|fstp?)([sl]?)$/) {
# unary float instructions
&lerr ("Wrong # of args\n") if ($#args != 0);
$op = $1;
$size = $2;
$size =~ tr/sl/lq/;
} elsif (/^(faddp?|fsubr?p?|fmulp?|fdivr?p?|fxch)([sl]?)$/) {
# float instructions with variable arity
&lerr ("Wrong # of args\n") if ($#args > 1);
$op = $1;
$size = $2;
$size =~ tr/sl/lq/;
if ($op !~ s/^fsubr/fsub/) {
$op =~ s/^fsub/fsubr/;
}
if ($#args == 1) {
@args = ($args[1], $args[0]); # Swap args if binary
}
} elsif (/^j/) {
# jump instructions
&lerr ("Wrong # of args\n") if ($#args != 0);
} else {
&lerr ("Unrecognized instruction: $_\n");
}
if ($op =~ /^j/) {
# jump instructions handled specially
$_ = $args[0];
if (!s/^\*//) {
$_ = &translate_sym ($_);
}
$_ = $op . " " . $_;
} else {
# First scan for int register refs which reveal operand size
if (0) { # Disable this code for now, it's too simplistic
foreach (@args) {
if (/^%/ && !/^%st/) {
$size = "";
}
}
}
foreach (@args) {
if (s/^%//) { # Register
} elsif (s/^\$//) { # Immediate constant
$_ = &translate_sym ($1) . $2 if (/^($re_sym)(.*)$/);
} elsif (/^(.*)\((.*)\)$/) { # Memory operand
$disp = $1;
$elms = $2;
$disp = "" if ($disp eq "0");
if (defined ($sym_table{$disp})) {
$symdisp = "";
$numdisp = "+" . &translate_sym ($disp);
} elsif ($disp =~ /^[0-9]/) {
$symdisp = "";
$numdisp = "+" . $disp;
} elsif ($disp =~ /^[-+]/) {
$symdisp = "";
$numdisp = $disp;
} else {
$symdisp = &translate_sym ($disp);
$numdisp = "";
}
($base,$index,$scale,$extra) = split (/\s*,\s*/, $elms);
$base =~ s/^%//;
$index =~ s/^%//;
&lerr ("Too many elements in mem ref\n") if ($extra ne "");
$_ = $size_prefix{$size} . $symdisp . "[" . $base;
$_ .= "+" . $index if $index ne "";
$_ .= "*" . $scale if $scale ne "";
$_ .= $numdisp . "]";
} elsif (/^($re_sym)(.*)$/) { # Symbol operand
$_ = &translate_sym ($1) . $2;
}
}
$_ = $op . " " . join (",", @args);
}
} else {
&lerr ("Unrecognized pattern: $_\n");
}
&append_line;
}
&end_repeat ("main");
&fatal ("Line $procstart: Missing endp\n") if ($proclabel ne "");
print $repeat_buf;
if (!$inline) {
print "_TEXT\tends\n";
print "\tend\n";
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -