最近、
最近のPICなどのマイコンには開発環境が用意されており、
PHPでアセンブラを作る
アセンブラをどの言語で作るかですが、


このアセンブラプログラムのPHPのソースはリスト1のようになります。
<?php
$labellist = array();
$codelist = array();
$datalist = array();
$codemap = array(
"movwf" => 0x0080,
"clrf" => 0x0180,
"subwf" => 0x0200,
"decf" => 0x0300,
"iorwf" => 0x0400,
"andwf" => 0x0500,
"xorwf" => 0x0600,
"addwf" => 0x0700,
"movf" => 0x0800,
"comf" => 0x0900,
"incf" => 0x0a00,
"decfsz" => 0x0b00,
"rrf" => 0x0c00,
"rlf" => 0x0d00,
"swapf" => 0x0e00,
"incfsz" => 0x0f00,
"bcf" => 0x1000,
"bsf" => 0x1400,
"btfsc" => 0x1800,
"btfss" => 0x1c00,
"call" => 0x2000,
"goto" => 0x2800,
"movlw" => 0x3000,
"retlw" => 0x3400,
"iorlw" => 0x3800,
"andlw" => 0x3900,
"xorlw" => 0x3a00,
"sublw" => 0x3c00,
"addlw" => 0x3e00,
"nop" => 0x8000,
"return" => 0x8008,
"retfie" => 0x8009,
"sleep" => 0x8063,
"clrwdt" => 0x8064,
"clrw" => 0x8100,
);
function evaloprand($str)
{
global $labellist;
$ret = 0;
if (($str = trim(strtolower($str))) == "")
return null;
if (substr($str, 0, 1) == '"')
return $str;
$remain = $str;
while ($remain != "") {
if (ereg('^([-+|&]?) *\((.*)$', $remain, $array)) {
$sign = $array[1];
$remain = $array[2];
$level = 1;
$pos = 0;
while ($level > 0) {
if ($pos >= strlen($remain))
die("unmatched bracket: ".htmlspecialchars($str)."\n");
switch (substr($remain, $pos++, 1)) {
case '(':
$level++;
break;
case ')':
$level--;
break;
}
}
$val = evaloprand(substr($remain, 0, $pos - 1));
$remain = substr($remain, $pos);
} else {
ereg('^([-+|&]?) *([^-+|&() ]+) *([-+|&()].*)?$', $remain, $array);
$sign = $array[1];
$val = $array[2];
$remain = $array[3];
if (ereg('^[0-9]', $val)) {
if (ereg('^[0-9]+$', $val))
$val += 0;
else if (ereg('^0x[0-9a-f]+$', $val))
$val += 0;
else if (ereg('^([0-9a-f]+)h$', $val, $array))
$val = ("0x".$array[1]) + 0;
else
die("invalid number: ".htmlspecialchars($str)."\n");
} else if (ereg("^h'([0-9a-f]+)'$", $val, $array))
$val = ("0x".$array[1]) + 0;
else if (($val = @$labellist[$val]) === null)
die("undefined label: ".htmlspecialchars($str)."\n");
}
switch ($sign) {
default:
case '+':
$ret += $val;
break;
case '-':
$ret -= $val;
break;
case '&':
$ret &= $val;
break;
case '|':
$ret |= $val;
break;
}
}
return $ret;
}
$locallabel = "";
$org = 0;
if (@$argv[1] === "-")
$remain = stream_get_contents(STDIN);
else {
if (($remain = @$_POST["src"]) === NULL) {
print <<<EOO
<HTML><HEAD><TITLE>picasm.php</TITLE></HEAD><BODY>
<H1>picasm.php</H1>
<FORM method=POST>
<TEXTAREA cols=80 rows=30 name=src>
</TEXTAREA>
<BR>
<INPUT type=submit>
</FORM>
<HR>
</BODY></HTML>
EOO;
die();
}
if (get_magic_quotes_gpc())
$remain = stripslashes($remain);
}
while ($remain != "") {
list($line, $remain) = split("\r|\n|\r\n", $remain, 2);
if (($i = strpos($line, ";")) !== FALSE)
$line = substr($line, 0, $i);
list($label, $opcode, $oprand) = split("[ \t]+", $line, 3);
$label = strtolower($label);
$opcode = strtolower($opcode);
$oprand = trim($oprand);
# printf("label:%s\n opcode:%s\n oprand:%s\n", $label, $opcode, $oprand);
if ($opcode == "org")
$org = $nextorg = evaloprand($oprand);
else {
$nextorg = $org + 1;
}
if ($label != "") {
if (ereg('^:', $label))
$s = $locallabel.$label;
else
$s = $locallabel = $label;
if ($opcode == "equ") {
$labellist[$s] = evaloprand($oprand);
continue;
}
$labellist[$s] = $org;
}
if (($l = @$codemap[$opcode]) !== null) {
if (@$codelistl[$org] !== null)
die("memory overwritten: ".htmlspecialchars($line)."\n");
$codelist[$org] = array($l, $oprand);
$org = $nextorg;
continue;
}
switch ($opcode) {
case "#include":
if (!ereg('^"([-_.0-9A-Za-z]+)"$', $oprand, $array))
die("syntax error: ".htmlspecialchars($line)."\n");
$remain = file_get_contents("include/".$array[1])."\n".$remain;
continue 2;
case "__config":
if (@$codemap[$addr = 0x2007] !== null)
die("memory overwritten: ".htmlspecialchars($line)."\n");
$codelist[$addr] = array(-1, $oprand);
continue 2;
case "nolist":
case "ifdef":
case "ifndef":
case "endif":
case "messg":
case "":
case "end":
case "list":
case "__maxram":
case "__badram":
continue 2;
case "org":
continue 2;
default:
die("syntax error: ".htmlspecialchars($line)."\n");
}
}
if (0) {
foreach ($labellist as $key => $val)
printf("%s\t%08x\n", $key, $val);
}
ksort($codelist);
foreach ($codelist as $key => $val) {
list($l, $oprand) = $val;
$array = explode(",", $oprand);
# $oprand1 = evaloprand($oprand1);
# $oprand2 = evaloprand($oprand2);
#printf("%08x: %04x %d, %d\n", $key, $l, $oprand1, $oprand2);
#continue;
if ($l < 0)
$l = evaloprand($oprand);
else if (($l & 0x8000)) {
if ($oprand != "")
die("syntax error: ".htmlspecialchars($line)."\n");
$l = $l & 0x3fff;
} else if (($l & 0x3000) == 0x3000) {
if (count($array) != 1)
die("syntax error: ".htmlspecialchars($line)."\n");
$oprand1 = evaloprand($oprand);
if (($oprand1 < 0)||($oprand1 > 0xff))
die("out of range: ".htmlspecialchars($line)."\n");
$l = $l | $oprand1;
} else if (($l & 0x3000) == 0x2000) {
if (count($array) != 1)
die("syntax error: ".htmlspecialchars($line)."\n");
$oprand1 = evaloprand($oprand);
if (($oprand1 < 0)||($oprand1 > 0x7ff))
die("out of range: ".htmlspecialchars($line)."\n");
$l = $l | $oprand1;
} else if (($l & 0x3000) == 0x1000) {
if (count($array) != 2)
die("syntax error: ".htmlspecialchars($line)."\n");
$oprand1 = evaloprand($array[0]);
if (($oprand1 < 0)||($oprand1 > 0x7f))
die("out of range: ".htmlspecialchars($line)."\n");
$oprand2 = evaloprand($array[1]);
if (($oprand2 < 0)||($oprand2 > 7))
die("out of range: ".htmlspecialchars($line)."\n");
$l = $l | $oprand1 | ($oprand2 << 7);
} else if (($l & 0x80)) {
if (count($array) != 1)
die("syntax error: ".htmlspecialchars($line)."\n");
$oprand1 = evaloprand($oprand);
if (($oprand1 < 0)||($oprand1 > 0x7f))
die("out of range: ".htmlspecialchars($line)."\n");
$l = $l | $oprand1;
} else {
if (count($array) != 2)
die("syntax error: ".htmlspecialchars($line)."\n");
$oprand1 = evaloprand($array[0]);
if (($oprand1 < 0)||($oprand1 > 0x7f))
die("out of range: ".htmlspecialchars($line)."\n");
$oprand2 = evaloprand($array[1]);
if (($oprand2 < 0)||($oprand2 > 1))
die("out of range: ".htmlspecialchars($line)."\n");
$l = $l | $oprand1 | ($oprand2 << 7);
}
#printf("%08x: %04x\n", $key, $l);
$codelist[$key] = $l;
}
header('Content-Type: text/plain');
print <<<EOO
:020000040000FA
EOO;
$s = "";
foreach ($codelist as $key => $val) {
if ($s == "")
$sum = 0;
$h = ($val >> 8) & 0xff;
$l = $val & 0xff;
$s .= sprintf("%02X%02X", $l, $h);
$sum += ($h + $l);
if ((@$codelist[$key + 1] === null)||(($key & 7) == 7)) {
$len = strlen($s) / 2;
$addr = ($key - ($len / 2 - 1)) * 2;
$sum += $len;
$sum += ($addr >> 8) & 0xff;
$sum += $addr & 0xff;
$sum = (0x10000 - $sum) & 0xff;
printf(":%02X%04X00%s%02X\n", strlen($s) / 2, $addr, $s, $sum);
$s = "";
}
}
print <<<EOO
:00000001FF
EOO;
?>
今回は、
まず、
アセンブラの擬似命令ですが、
また、
アセンブラ作りの第一歩
さて、
アセンブラの最大の特徴は、
命令に与えるパラメータも、*(q++)=*(p++);
と書けますが、
こうして見ると、
そんなわけで、