Advertisement
Drakia

Untitled

May 10th, 2012
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 6.57 KB | None | 0 0
  1. <?php
  2.     if (!isset($_REQUEST['asm'])) {
  3.         echo "Stack Machine Assembler<br/>";
  4.         echo "<form method=\"post\">";
  5.         echo "<textarea name=\"asm\" rows=\"30\" cols=\"100\"></textarea><br>";
  6.         echo "<input type=\"submit\" value=\"Assemble\">";
  7.         echo "</form>";
  8.     } else {
  9.         $lines = explode("\n", $_REQUEST['asm']);
  10.         if (count($lines) == 0) {
  11.             echo "You need to supply input";
  12.             die();
  13.         }
  14.         $SYMBOLTABLE = array('PSW' => 'FFFB',
  15.                              'A' => 'FFFC',
  16.                              'B' => 'FFFD',
  17.                              'C' => 'FFFE',
  18.                              'D' => 'FFFF');
  19.         $FUNCTABLE = array('nop' => array('00', 0),
  20.                            'halt' => array('01', 0),
  21.                            'pushimm' => array('02', 1),
  22.                            'pushext' => array('03', 2),
  23.                            'popinh' => array('04', 0),
  24.                            'popext' => array('05', 2),
  25.                            'jnz' => array('06', 2),
  26.                            'jnn' => array('0A', 2),
  27.                            'add' => array('07', 0),
  28.                            'sub' => array('08', 0),
  29.                            'nor' => array('09', 0));
  30.  
  31.         // Pass 1, parse commands, throw symbols into tables.
  32.         for ($i = 0; $i < count($lines); $i++) {
  33.             $line = $lines[$i];
  34.  
  35.             // Find comment on line if it exists. Strip it from line.
  36.             $commPos = strpos($line, '--'); // Find comment position (If it exists)
  37.             $comment = '';
  38.             if ($commPos === false) $commPos = strlen($line);
  39.             else $comment = substr($line, $commPos); // Store comment
  40.             $line = substr($line, 0, $commPos); // Strip comment.
  41.             $line = trim($line); // Remove space from before/after command.
  42.             if ($line== '') continue; // If line is blank, not a command, skip it.
  43.    
  44.             // Find if there's a label, add it to symbol table.
  45.             $symPos = strpos($line, ':');
  46.             $symbol = '';
  47.             if ($symPos !== false) {
  48.                 $symbol = substr($line, 0, $symPos);
  49.                 $line = trim(substr($line, $symPos + 1));
  50.                 if ($line == '') continue;
  51.                 $SYMBOLTABLE[$symbol] = dechex(count($parse)); // Set symbol table entry to address.
  52.             }
  53.            
  54.             // Replace the line in the list with the line minus symbol, and minus comment.
  55.             $lines2[] = $line;
  56.            
  57.             // Check for function, replace. Make sure to leave room for operand
  58.             $funcEnd = strpos($line, ' ');
  59.             if ($funcEnd === false) $funcEnd = strlen($line);
  60.             $func = substr($line, 0, $funcEnd);
  61.             if (array_key_exists($func, $FUNCTABLE)) {
  62.                 $parse[] = str_pad(base_convert($FUNCTABLE[$func][0], 16, 2), 8, '0', STR_PAD_LEFT).' '.$line;
  63.                if ($symbol != '') $parse[count($parse) - 1] .= ' ['.$symbol.' = 0x'.$SYMBOLTABLE[$symbol].']';
  64.                 // Create room for the added data in parse 2
  65.                 for ($j = 0; $j < $FUNCTABLE[$func][1]; $j++)
  66.                     $parse[] = '';
  67.             } else
  68.                 die("Problem parsing ASM, unknown function $func");
  69.         }
  70.  
  71.         $pLoc = 0;
  72.         for ($i = 0; $i < count($parse); $i++) {
  73.             // Increase our internal pointer if this is a command. And skip over it.
  74.             if ($parse[$i] != '') {
  75.                 $pLoc++;
  76.                 $parse2[] = $parse[$i];
  77.                 continue;
  78.             }
  79.  
  80.             // Grab the current working line. This will be function and operand only
  81.             $line = $lines2[$pLoc - 1];
  82.             $funcEnd = strpos($line, ' ');
  83.             if ($funcEnd === false) $funcEnd = strlen($line);
  84.             $func = substr($line, 0, $funcEnd);
  85.             $operand = substr($line, $funcEnd + 1);
  86.            
  87.             // Check if we have a symbol that matches this, a function, or a +/- operation. Otherwise it is a hex value.
  88.             $fun = '';
  89.             if (strpos($operand, "(") !== false) {
  90.                 $fun = $operand[0];
  91.                 if ($fun != 'L' && $fun != 'H') {
  92.                     die("Invalid function call");
  93.                 }
  94.                 $operand = substr($operand, 2, -1);
  95.             }
  96.             if ($operand[0] == '+' || $operand[0] == '-') {
  97.                 if ($operand[strlen($operand)-1] == 'h') $base = 16;
  98.                 else $base = 10;
  99.                 $operand = $i + intval(substr($operand, 0, strlen($operand)-1), $base) - 1;
  100.                 $operand = base_convert($operand, 10, 2);
  101.             } else if (@array_key_exists($operand, $SYMBOLTABLE)) {
  102.                 $operand = base_convert($SYMBOLTABLE[$operand], 16, 2);
  103.             } else {
  104.                 $pos = strpos($operand, '+');
  105.                 if ($pos === false) $pos = strpos($operand, '-');
  106.                 if ($pos === false)
  107.                     $operand = base_convert($operand, 16, 2);
  108.                 else {
  109.                     $off = substr($operand, $pos + 1);
  110.                     if (substr($off, -1) == 'h') $off = intval(base_convert(substr($off, 0, -1), 16, 10));
  111.                     else if (substr($off, -1) == 'd') $off = intval(substr($off, 0, -1));
  112.                     else $off = intval($off);
  113.                     $operand = substr($operand, 0, $pos);
  114.                     if (@array_key_exists($operand, $SYMBOLTABLE)) {
  115.                         $operand = base_convert((hexdec($SYMBOLTABLE[$operand]) + $off), 10, 2);
  116.                     } else
  117.                         die("Can't offset constant value");
  118.                 }
  119.             }
  120.             if ($fun != '') {
  121.                 $operand = str_pad($operand, 16, '0', STR_PAD_LEFT);
  122.                 if ($fun == 'L')
  123.                     $operand = substr($operand, 8, 8);
  124.                 else
  125.                     $operand = substr($operand, 0, 8);
  126.             } else
  127.                 $operand = str_pad($operand, $FUNCTABLE[$func][1]*8, '0', STR_PAD_LEFT);
  128.  
  129.             // Push the output value to parse2, the final machine code.
  130.             for ($j = 0; $j < $FUNCTABLE[$func][1]; $j++) {
  131.                 $parse2[] = substr($operand, $j * 8, 8);
  132.             }
  133.             // We are on the first operand, so increase i by one less than the operand count.
  134.             $i += $FUNCTABLE[$func][1] - 1;
  135.         }
  136.  
  137.         // Output the machine code to console
  138.         for ($i = 0; $i < count($parse2); $i++) {
  139.             echo $parse2[$i]."\n";
  140.         }
  141.     }
  142. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement