⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gas2intel

📁 这是一个mp3的源代码
💻
字号:
#!/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 + -