Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- if (!isset($_REQUEST['asm'])) {
- echo "Stack Machine Assembler<br/>";
- echo "<form method=\"post\">";
- echo "<textarea name=\"asm\" rows=\"30\" cols=\"100\"></textarea><br>";
- echo "<input type=\"submit\" value=\"Assemble\">";
- echo "</form>";
- } else {
- $lines = explode("\n", $_REQUEST['asm']);
- if (count($lines) == 0) {
- echo "You need to supply input";
- die();
- }
- $SYMBOLTABLE = array('PSW' => 'FFFB',
- 'A' => 'FFFC',
- 'B' => 'FFFD',
- 'C' => 'FFFE',
- 'D' => 'FFFF');
- $FUNCTABLE = array('nop' => array('00', 0),
- 'halt' => array('01', 0),
- 'pushimm' => array('02', 1),
- 'pushext' => array('03', 2),
- 'popinh' => array('04', 0),
- 'popext' => array('05', 2),
- 'jnz' => array('06', 2),
- 'jnn' => array('0A', 2),
- 'add' => array('07', 0),
- 'sub' => array('08', 0),
- 'nor' => array('09', 0));
- // Pass 1, parse commands, throw symbols into tables.
- for ($i = 0; $i < count($lines); $i++) {
- $line = $lines[$i];
- // Find comment on line if it exists. Strip it from line.
- $commPos = strpos($line, '--'); // Find comment position (If it exists)
- $comment = '';
- if ($commPos === false) $commPos = strlen($line);
- else $comment = substr($line, $commPos); // Store comment
- $line = substr($line, 0, $commPos); // Strip comment.
- $line = trim($line); // Remove space from before/after command.
- if ($line== '') continue; // If line is blank, not a command, skip it.
- // Find if there's a label, add it to symbol table.
- $symPos = strpos($line, ':');
- $symbol = '';
- if ($symPos !== false) {
- $symbol = substr($line, 0, $symPos);
- $line = trim(substr($line, $symPos + 1));
- if ($line == '') continue;
- $SYMBOLTABLE[$symbol] = dechex(count($parse)); // Set symbol table entry to address.
- }
- // Replace the line in the list with the line minus symbol, and minus comment.
- $lines2[] = $line;
- // Check for function, replace. Make sure to leave room for operand
- $funcEnd = strpos($line, ' ');
- if ($funcEnd === false) $funcEnd = strlen($line);
- $func = substr($line, 0, $funcEnd);
- if (array_key_exists($func, $FUNCTABLE)) {
- $parse[] = str_pad(base_convert($FUNCTABLE[$func][0], 16, 2), 8, '0', STR_PAD_LEFT).' '.$line;
- if ($symbol != '') $parse[count($parse) - 1] .= ' ['.$symbol.' = 0x'.$SYMBOLTABLE[$symbol].']';
- // Create room for the added data in parse 2
- for ($j = 0; $j < $FUNCTABLE[$func][1]; $j++)
- $parse[] = '';
- } else
- die("Problem parsing ASM, unknown function $func");
- }
- $pLoc = 0;
- for ($i = 0; $i < count($parse); $i++) {
- // Increase our internal pointer if this is a command. And skip over it.
- if ($parse[$i] != '') {
- $pLoc++;
- $parse2[] = $parse[$i];
- continue;
- }
- // Grab the current working line. This will be function and operand only
- $line = $lines2[$pLoc - 1];
- $funcEnd = strpos($line, ' ');
- if ($funcEnd === false) $funcEnd = strlen($line);
- $func = substr($line, 0, $funcEnd);
- $operand = substr($line, $funcEnd + 1);
- // Check if we have a symbol that matches this, a function, or a +/- operation. Otherwise it is a hex value.
- $fun = '';
- if (strpos($operand, "(") !== false) {
- $fun = $operand[0];
- if ($fun != 'L' && $fun != 'H') {
- die("Invalid function call");
- }
- $operand = substr($operand, 2, -1);
- }
- if ($operand[0] == '+' || $operand[0] == '-') {
- if ($operand[strlen($operand)-1] == 'h') $base = 16;
- else $base = 10;
- $operand = $i + intval(substr($operand, 0, strlen($operand)-1), $base) - 1;
- $operand = base_convert($operand, 10, 2);
- } else if (@array_key_exists($operand, $SYMBOLTABLE)) {
- $operand = base_convert($SYMBOLTABLE[$operand], 16, 2);
- } else {
- $pos = strpos($operand, '+');
- if ($pos === false) $pos = strpos($operand, '-');
- if ($pos === false)
- $operand = base_convert($operand, 16, 2);
- else {
- $off = substr($operand, $pos + 1);
- if (substr($off, -1) == 'h') $off = intval(base_convert(substr($off, 0, -1), 16, 10));
- else if (substr($off, -1) == 'd') $off = intval(substr($off, 0, -1));
- else $off = intval($off);
- $operand = substr($operand, 0, $pos);
- if (@array_key_exists($operand, $SYMBOLTABLE)) {
- $operand = base_convert((hexdec($SYMBOLTABLE[$operand]) + $off), 10, 2);
- } else
- die("Can't offset constant value");
- }
- }
- if ($fun != '') {
- $operand = str_pad($operand, 16, '0', STR_PAD_LEFT);
- if ($fun == 'L')
- $operand = substr($operand, 8, 8);
- else
- $operand = substr($operand, 0, 8);
- } else
- $operand = str_pad($operand, $FUNCTABLE[$func][1]*8, '0', STR_PAD_LEFT);
- // Push the output value to parse2, the final machine code.
- for ($j = 0; $j < $FUNCTABLE[$func][1]; $j++) {
- $parse2[] = substr($operand, $j * 8, 8);
- }
- // We are on the first operand, so increase i by one less than the operand count.
- $i += $FUNCTABLE[$func][1] - 1;
- }
- // Output the machine code to console
- for ($i = 0; $i < count($parse2); $i++) {
- echo $parse2[$i]."\n";
- }
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement