123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- use warnings;
- use strict;
- use Data::Dumper;
- my $VERSION = 0.01;
- my @program;
- my %opcodes = (
- "add" => "01",
- "mult" => "02",
- "in" => "03",
- "out" => "04",
- "jpt" => "05",
- "jpf" => "06",
- "lt" => "07",
- "eq" => "08",
- "mrb" => "09",
- "hlt" => "99",
- );
- sub load
- {
- my $loadAddress = shift;
- my $valueToLoad = shift;
- $program[$loadAddress] = $valueToLoad;
- }
- sub parseAssembly
- {
- my @assembly = @_;
-
- my %labels;
-
- my $instructionNumber = 0;
- foreach my $line (@assembly)
- {
- $line =~ /^(\w+?:?)(?: (.+))?$/;
- my $asmInstruction = $1;
- my @parameters = split(/,\s?/, $2 || "");
-
- if($asmInstruction =~ /:$/)
- {
- $labels{substr($asmInstruction, 0, -1)} = ++$instructionNumber;
- next;
- }
- if($asmInstruction eq "ld")
- {
- my $storeAt = getAddress(shift @parameters);
- my $value = shift @parameters;
- load($storeAt, $value);
- }
- elsif($opcodes{$asmInstruction})
- {
- parseOpcodeAndParams($opcodes{$asmInstruction}, \@parameters, \$instructionNumber);
- }
- else
- {
- die "Failed to find matching ASM instruction for: $asmInstruction";
- }
- }
- }
- sub parseOpcodeAndParams
- {
-
-
- my $instructionNumber = $_[2];
-
- my $opcode = $_[0];
-
- my $opcodeIdx = $$instructionNumber++;
-
- my @parameters = @{ $_[1] };
-
- my $storeAt = $#parameters > 0 ? getAddress(pop(@parameters)) : -1;
-
- my $parameterModeIdx = 2;
- foreach my $param (@parameters)
- {
- if(isImmediate($param))
- {
- if(length($opcode) < $parameterModeIdx)
- {
- $opcode = "0$opcode";
- }
- $opcode = "1$opcode";
- }
- else
- {
- $param = getAddress($param);
- }
- $parameterModeIdx++;
- $program[$$instructionNumber++] = $param;
- if($$instructionNumber == 9)
- {
- print "$opcode, $param";
- die "Overwriting memory!";
- }
- }
-
- $program[$opcodeIdx] = $opcode;
- if($storeAt > -1)
- {
-
- $program[$$instructionNumber++] = $storeAt;
- }
- }
- sub isImmediate
- {
- return !(shift =~ /^0d/);
- }
- sub getAddress
- {
- return (shift =~ s/^0d//r);
- }
- sub readFile
- {
- my @assembly;
- my $filePath = shift;
- open(my $fh, "<", $filePath) or die "Failed to open file";
- while(my $line = <$fh>)
- {
- chomp $line;
-
- $line =~ s/\/\/.+$//;
-
- $line =~ s/\s+$//;
- if ($line ne "") {
- push(@assembly, $line);
- }
- }
- return @assembly;
- }
- parseAssembly(readFile($ARGV[0]));
- print "[".join(",", @program)."]\n";
|