use strict; use warnings; use QNICE qw/:all/; use Getopt::Long; use Data::Dumper; $Data::Dumper::Indent=1; my $max_mem = 0xFFFF; GetOptions( \my %opt, "source=s", "binary=s", "listing=s", "disassemble", "help", ) or printhelp(); printhelp() if $opt{help} or ($opt{disassemble} and !$opt{binary}) or (!$opt{disassemble} and !$opt{source}); if ( $opt{disassemble} ) { disasm(); } else { asm() } sub asm { open(my $source, '<', $opt{source}) or die "couldn't read '$opt{source}', $!"; my @code = map { chomp; $_ } <$source>; # arrays for results, passed by reference my %bin = (); my @errors = (); my %cmap = (); my $bin_hdl; if ( $opt{binary} ) { open($bin_hdl, '>', $opt{binary}) or die "couldn't write '$opt{binary}', $!"; } else { $bin_hdl = \*STDOUT; } if ( assemble(\@code, \%bin, \@errors, \%cmap) ) { print $bin_hdl "$_ $bin{$_}", "\n" for sort(keys(%bin)); if ( $opt{listing} ) { open(my $list, '>', $opt{listing}) or die "couldn't write '$opt{listing}', $!"; for my $lnbr (1..@code) { my $addr = $cmap{$lnbr} || 0; printf $list "%13s %s\n", '', $code[$lnbr-1] and next unless $addr; for my $a (@$addr) { my $bin = $bin{$a} || ''; my $code = $a eq $addr->[0] ? $code[$lnbr-1] : ''; printf $list "%6s %6s %s\n", $a, $bin, $code; } } } } else { # TODO Warum hat $_->{source} ein newline am Anfang? warn "$_->{level}: $_->{text} line $_->{line}; $_->{source}\n" for @errors; } } sub disasm { # init memory and registers my $mem = init_memory($max_mem); my $reg = init_registers(); my $changed = {}; open(my $binfh, '<', $opt{binary}) or die "couldn't read '$opt{binary}', $!"; # load assembled code into memory my $loaded = loadbin($mem, [<$binfh>]); # disassemble from memory my $dcode = init_code($mem); disassemble($mem, $dcode); my $src_hdl; if ( $opt{source} ) { open($src_hdl, '>', $opt{source}) or die "couldn't write '$opt{source}', $!"; } else { $src_hdl = \*STDOUT; } for my $i ( 0..$max_mem ) { printf $src_hdl "0x%04X 0x%4s %s\n", $i, $mem->[$i], $dcode->[$i] if exists($loaded->{sprintf "0x%04X", $i}); } } sub printhelp { print <<'EOF'; qcmd: qnice (dis)assembler assemble: qcmd -s [-b ] [-l ] disassemble: qcmd -d -b [-s ] EOF exit; }