add、sub、and、or、slt、lw、sw、addi、beq、j
测试程序如下:
main: addi $2, $0, 5
addi $3, $0, 12
addi $7, $3, -9
or $4, $7, $2
and $5, $3, $4
add $5, $5, $4
beq $5, $7, end
slt $4, $3, $4
beq $4, $0, around
addi $5, $0, 0
around: slt $4, $7, $2
add $7, $4, $5
sub $7, $7, $2
sw $7, 68($3)
lw $2, 80($0)
j end
addi $2, $0, 1
end: sw $2, 84($0)
转换后的机器码如下(十六进制):
20020005
2003000c
2067fff7
00e22025
00642824
00a42820
10a7000a
0064202a
10800001
20050000
00e2202a
00853820
00e23822
ac670044
8c020050
08000011
20020001
ac020054
附Perl脚本:assembler.rar
#!/usr/bin/perl
open FileIN,"$ARGV[0]";
chomp($_=$ARGV[0]);
/(.*)\.asm/;
open FileOUT,">$1.o";
$instr_addr=0;
while($line=<FileIN>){
$_=$line;
next if(!/[a-zA-Z0-9,\$]+/);
chomp($_);
if(/(.*)[ \t]*:.*/){
$label_addr{$1}=$instr_addr;
}
$instr_addr+=4;
}
open FileIN,"$ARGV[0]";
$instr_addr=0;
while($line=<FileIN>){
$_=$line;
next if(!/[a-zA-Z0-9,\$]+/);
chomp($_);
if(/.*:(.*)/){
$_=$1;
}
#for instructions like "XX XX, XX, XX"
if(/[ \t]*([a-zA-Z]*)[ \t]*(.*)[ \t]*,[ \t]*(.*)[ \t]*,[ \t]*(.*)[ \t]*/) {
$p1=$1; $p2=$2 ;$p3=$3; $p4=$4;
$instr_code="";
if($p1 eq "add") {
$op=0;
$p2=~/\$([0-9]*)/; $rd=$1;
$p3=~/\$([0-9]*)/; $rs=$1;
$p4=~/\$([0-9]*)/; $rt=$1;
$instr_code=$op*2**26+$rs*2**21+$rt*2**16+$rd*2**11+32;
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
if($p1 eq "sub") {
$op=0;
$p2=~/\$([0-9]*)/; $rd=$1;
$p3=~/\$([0-9]*)/; $rs=$1;
$p4=~/\$([0-9]*)/; $rt=$1;
$instr_code=$op*2**26+$rs*2**21+$rt*2**16+$rd*2**11+34;
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
if($p1 eq "and") {
$op=0;
$p2=~/\$([0-9]*)/; $rd=$1;
$p3=~/\$([0-9]*)/; $rs=$1;
$p4=~/\$([0-9]*)/; $rt=$1;
$instr_code=$op*2**26+$rs*2**21+$rt*2**16+$rd*2**11+36;
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
if($p1 eq "or") {
$op=0;
$p2=~/\$([0-9]*)/; $rd=$1;
$p3=~/\$([0-9]*)/; $rs=$1;
$p4=~/\$([0-9]*)/; $rt=$1;
$instr_code=$op*2**26+$rs*2**21+$rt*2**16+$rd*2**11+37;
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
if($p1 eq "slt") {
$op=0;
$p2=~/\$([0-9]*)/; $rd=$1;
$p3=~/\$([0-9]*)/; $rs=$1;
$p4=~/\$([0-9]*)/; $rt=$1;
$instr_code=$op*2**26+$rs*2**21+$rt*2**16+$rd*2**11+42;
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
if($p1 eq "addi") {
$op=8;
$p2=~/\$([0-9]*)/; $rt=$1;
$p3=~/\$([0-9]*)/; $rs=$1;
$addr=$p4;
if($addr ge 0) {
$instr_code=$op*2**26+$rs*2**21+$rt*2**16+$addr;
} else {
$instr_code=$op*2**26+$rs*2**21+($rt+1)*2**16+$addr;
}
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
if($p1 eq "beq") {
$op=4;
$p2=~/\$([0-9]*)/; $rs=$1;
$p3=~/\$([0-9]*)/; $rt=$1;
$addr=($label_addr{$p4}-$instr_addr-4)/4;
if($addr ge 0) {
$instr_code=$op*2**26+$rs*2**21+$rt*2**16+$addr;
} else {
$instr_code=$op*2**26+$rs*2**21+($rt+1)*2**16+$addr;
}
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
}
#for instructions like "XX XX, XX(XX)"
if(/[ \t]*([a-zA-Z]*)[ \t]*(.*)[ \t]*,[ \t]*([0-9]*)\((.*)\)[ \t]*/) {
$p1=$1; $p2=$2; $p3=$3; $p4=$4;
if($p1 eq "lw") {
$op=35;
$p2=~/\$([0-9]*)/; $rt=$1;
$p4=~/\$([0-9]*)/; $rs=$1;
$addr=$p3;
if($addr ge 0) {
$instr_code=$op*2**26+$rs*2**21+$rt*2**16+$addr;
} else {
$instr_code=$op*2**26+$rs*2**21+($rt+1)*2**16+$addr;
}
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
if($p1 eq "sw") {
$op=43;
$p2=~/\$([0-9]*)/; $rt=$1;
$p4=~/\$([0-9]*)/; $rs=$1;
$addr=$p3;
if($addr ge 0) {
$instr_code=$op*2**26+$rs*2**21+$rt*2**16+$addr;
} else {
$instr_code=$op*2**26+$rs*2**21+($rt+1)*2**16+$addr;
}
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
}
#for instructions like "XX XX"
if(/[ \t]*([a-zA-Z]*)[ \t]*(.*)[ \t]*/) {
$p1=$1; $p2=$2;
if($p1 eq "j") {
$op=2;
$addr=$label_addr{$p2}/4;
$instr_code=$op*2**26+$addr;
$out_code=&dec2hex($instr_code);
print FileOUT "$out_code\n";
}
}
$instr_addr+=4;
}
close FileIN;
close FileOUT;
sub dec2hex {
$tmp=sprintf "%x",$_[0];
$length=length($tmp);
if($length != 8) {
$i=8-$length;
while($i) {
$tmp="0$tmp";
$i-=1;
}
sprintf "$tmp";
} else {
sprintf "%x",$_[0];
}
}










