Monday, May 2, 2016

IRIS Disassembly

This page is a part of the "Understanding IRIS" collection.  Many thanks to David Takle, for figuring this out, and sharing this with us:

-----------------------------------------------------------

I got a bit curious about the QIC tapes that you have managed to read. Not sure what you have deciphered about what is on them, so I wrote a little script to translate the binary into something that looks like a DSP listing.

[DART Utility Disassembly]

file01

file02

Attached you will see 'file01' and 'file02' which correspond to the first 2 files in the zip file you had on line which contained 24 files.  Based on what I'm seeing there, it looks like that tape was primarily for diagnostics. 'file01' is like a boot program that reads in 'file02' which acts more like a menu system to the rest of the tape. If you scan down file02 you will see ASCII that gives the names of the various utilities on the tape.

[IRIS Disk Image Disassembly]

file-iris

I also translated the first 256 blocks on the big IRIS tape I found on your site. It appears to be a mirror image of an IRIS disk, block by block. 

If you consider that every 400 octal words is one disk block, you can see the boundaries between blocks.

Block zero was apparently the boot sector, but it seems to have been altered to disable it for some reason. It has too many HALT commands in the wrong places.

Block one is clearly the INDEX header block.

Block 3 looks like the ACCOUNTS header.

And so on. I have yet to locate anything that looks like REX (Real Time Executive) so either this is something other that LU0, or else the Star systems were laid out differently. The IRIS systems I remember had the REX header in block 2, so that the boot loader could read up the entire IRIS system into memory based on the block list it found there. So I'm still not sure what kind of LU that tape was made from.

If you are interested in the script I wrote to do this translating, you are welcome to it. But it's written in PHP. Not sure if you are familiar with that or not.

Happy hunting!
~David

------------------------------------------------------------------------------------

Looks like the Point_4_Computer_User manual has a great tutorial in assembler language starting on PDF Page 139.

------------------------------------------------------------------------------------

The PHP program that David wrote to perform the above disassembly can be found here:

"I'm attaching the source evaluator program. I've modified it to create a text file (.src) instead of an html file. It is designed to run on a local web server. So if you don't have one (I use WAMP) and want to run it on a remote server, you will have to alter the filenames accordingly, since it cannot then store files on your local drive.

The following lines are important to note:


lines 3-4 == you have to edit the filenames depending on what you want to analyze, as well as the path to where the files are,



line 32 == unpack == some of your tapes are big endian format, some are little endian. Changing the format letter ('v' or 'n') will switch between the 2 formats.

        probably the easiest way to tell if you have it right is that most of the filler space should be 77377. If it shows up as 177576, you need the other format.



Lines 47-48 == showByte() == you might have to swap these two lines if the text displays backwards, again due to endian format."


<?php
//
$filename = "f:\\www\\nova\\MinicomDiskUtility.bin";
$outputFile = "f:\\www\\nova\\MinicomDiskUtility.src";
//
$function = array( 0=>'COM', 1=>'NEG', 2=>'MOV', 3=>'INC', 4=>'ADC', 5=>'SUB', 6=>'ADD', 7=>'AND');
$carry = array( 0=>'', 1=>'Z', 2=>'O', 3=>'C');
$shift = array( 0=>'', 1=>'L', 2=>'R', 3=>'S');
$noload = array( 0=>'', 1=>'#');
$skip = array( 1=>'SKP', 2=>'SZC', 3=>'SNC', 4=>'SZR', 5=>'SNR', 6=>'SEZ', 7=>'SBN' );
$transfer = array( 0=>'NIO', 1=>'DIA', 2=>'DOA', 3=>'DIB', 4=>'DOB', 5=>'DIC', 6=>'DOC', 7=>'SKP' );
$busy = array( 0=>'BN', 1=>'BZ', 2=>'DN', 3=>'DZ');
$ioctl = array( 0=>'', 1=>'S', 2=>'C', 3=>'P');
$memFunction = array( 0=>'JMP', 1=>'JSR', 2=>'ISZ', 3=>'DSZ');
$ldasta = array( 0=>'???', 1=>'LDA', 2=>'STA', 3=>'???');
//
$zeros = '0000000000000000';
$alpha = '................................'
. ' !"#$%&' . "'" . '()*+,-./0123456789:;<=>?@'
. 'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`'
. 'abcdefghijklmnopqrstuvwxyz{|}~.';
//
$handle = fopen($filename, "rb");
echo $filename;
//
// loop thru file
$decloc = -1;
$listing = "\r\n";
while (!feof($handle)) {
if ($decloc > 32760) break;
$contents = fread($handle, 8192);
$data = unpack ( 'n*', $contents );  // 'v*' or 'n*' depending on endian order
$char = unpack ( 'C*', $contents );
$c = 1;
foreach ($data as $decitem ) {
$decloc = $decloc + 1;
// display address
$address = decoct($decloc);
$display = '00000' . $address;
$listing .= substr($display, strlen($display)-5 ,5) . ': ';
// display data
$octal = decoct($decitem);
$len = strlen($octal);
if ($len < 6) $listing .= substr('      ', 0, 6 - $len);
$listing .= $octal . '  ';
// display ascii
showByte($char[$c]); // may need to swap these 2 cmds, depending on endian order
showByte($char[$c+1]);  // may need to swap these 2 cmds, depending on endian order
$c = $c + 2;
// display instruction
$listing .= '  ';
$instr = decbin($decitem); // convert to binary
$len = strlen($instr);
if ($len < 16)
$instr = substr($zeros, 0, 16-$len) . $instr;
if (substr($instr,0,1) == '1') {
// arithmetic
$src = bindec(substr($instr,1,2));
$dst = bindec(substr($instr,3,2));
$fnc = bindec(substr($instr,5,3));
$shf = bindec(substr($instr,8,2));
$cry = bindec(substr($instr,10,2));
$nol = bindec(substr($instr,12,1));
$skp = bindec(substr($instr,13,3));
$command = $function[$fnc] . $carry[$cry] . $shift[$shf] . $noload[$nol]
. ' ' . $src . ',' . $dst;
if ($skp > 0)
$command .= ',' . $skip[$skp];
} elseif (substr($instr,1,2) == '11') {
// i/o instruction
$acs = bindec(substr($instr,3,2));
$xfr = bindec(substr($instr,5,3));
$ctl = bindec(substr($instr,8,2));
$dvc = decoct(bindec(substr($instr,10,6)));
$command = $transfer[$xfr];
if ($xfr == 7) 
$command .= $busy[$ctl];
else
$command .= $ioctl[$ctl];
$command .= ' ' . $acs . ',' . $dvc;
} elseif (substr($instr,1,2) == '00') {
// mem access instruction
$fnc = bindec(substr($instr,3,2));
$command = $memFunction[$fnc] . ' ' . memAddress($instr);
} else {
// LDA or STA
$fnc = bindec(substr($instr,1,2));
$acs = bindec(substr($instr,3,2));
$command = $ldasta[$fnc] . ' ' . $acs . ',' . memAddress($instr);

$listing .= $command;
$listing .= "\r\n";
}
} // end while
fclose($handle);
$fp = fopen($outputFile, "w");
fwrite($fp,$listing);
fclose($fp);


function memAddress( $binary ) {
global $decloc;
$ind = bindec(substr($binary,5,1));
$idx = bindec(substr($binary,6,2));
$dsp = bindec(substr($binary,8,8));
$indirect = ($ind == 0) ? '' : '@' ;
if ($idx == 0) {
// page zero
$displ = decoct($dsp);
} else {
if ($dsp > 128) { 
$dsp = ($dsp - 256) * -1;
$sign = '-';
} else {
$sign = ($idx == 1) ? '+' : '' ;
}
if ($idx == 1)  {
// relative to current location
if ($sign == '-')
$dest = decoct($decloc - $dsp);
else
$dest = decoct($decloc + $dsp);
$displ = '.' . $sign . decoct($dsp) . '    ; ' . $dest;
} else {
// relative to accum 2/3
$displ = $sign . decoct($dsp) . ',' . $idx;
}
}
$addr = $indirect . $displ;
return $addr;
}

function showbyte($dc) {
global $alpha, $listing;
if ($dc >=128) $dc = $dc - 128;
$listing .= substr($alpha, $dc, 1);
}

?>

------------------------------------------------------------------------------------

See also Tom Trebisky's fantastic page on the NOVA & Point 4 Assembler Language.

And then, my page chronicling Tom's assistance with building this.  Thank you again, Tom, your assistance here, together with David's, is invaluable.

------------------------------------------------------------------------------------

This page is a part of the "Understanding IRIS" collection.  

No comments:

Post a Comment