From 8f8cc64d10abb7a035773a9d3a38385bc6431d1b Mon Sep 17 00:00:00 2001 From: Warren Toomey Date: Fri, 26 Feb 2016 20:56:31 +1000 Subject: [PATCH] I've added tad and sza to the a7out simulator, and I also added some code to place command-line arguments into the simulated memory. I'm trying to write my own version of cat so I can compare mine to the real one. Right now there's a bug when simplecat has two arguments. Zero and one arguments are OK! Saving so I have a backup before proceeding. --- tools/a7out | 111 ++++++++++++++++++++++++++++++++++++++++++---- tools/simplecat.s | 77 +++++++++++++++++++++++++++++++- 2 files changed, 178 insertions(+), 10 deletions(-) diff --git a/tools/a7out b/tools/a7out index 2de634a..0a68cab 100755 --- a/tools/a7out +++ b/tools/a7out @@ -27,11 +27,12 @@ if ( ( @ARGV > 0 ) && ( $ARGV[0] eq "-d" ) ) { } # Check the arguments -die("Usage: $0 [-d] a.outfile\n") if ( @ARGV != 1 ); +die("Usage: $0 [-d] a.outfile [arg1 arg2 ...]\n") if ( @ARGV < 1 ); # Load the a.out file into memory # and simulate it -load_code( $ARGV[0] ); +load_code( shift(@ARGV) ); +set_arguments(@ARGV); simulate(); exit(0); @@ -67,6 +68,62 @@ sub load_code { close($IN); } +### Copy the arguments into the PDP-7 memory space, and build +### an array of pointers to these arguments. Build a pointer +### at 017777 that points at the array. +### +### At the moment, this is NOT what PDP-7 Unix uses, but it's +### a start and it will help us to grok the real thing. +### +### For now, assume abc, def and ghi are stored in memory. +### The layout of the pointers and strings would be: +### +### +-------+ +### | | +### | +-----|---------+ +### | | | | +### | | +---|---------|---------+ +### | | | | | | +### | | | V V V +### |o|o|o|0|||| \&dac, oct("020") => \&lac, + oct("034") => \&tad, oct("060") => \&jmp, oct("070") => \&iot, oct("074") => \&special, @@ -123,7 +181,7 @@ sub lac { # Deposit AC sub dac { my ( $instruction, $indirect, $addr ) = @_; - printf( STDERR "PC %06o: dac AC (value %08o) into %05o into AC\n", + printf( STDERR "PC %06o: dac AC (value %08o) into %05o\n", $PC, $AC, $addr ) if ($debug); if ($indirect) { @@ -134,6 +192,20 @@ sub dac { $PC++; } +# Add to AC +sub tad { + my ( $instruction, $indirect, $addr ) = @_; + printf( STDERR "PC %06o: tac AC (value %08o) from addr %05o\n", + $PC, $AC, $addr ) + if ($debug); + if ($indirect) { + $AC += $Mem[ $Mem[$addr] & 017777 ]; + } else { + $AC+= $Mem[$addr]; + } + $PC++; +} + # Jump sub jmp { my ( $instruction, $indirect, $addr ) = @_; @@ -153,15 +225,20 @@ sub special { exit(1); } if ( $instruction == 0741100 ) { # spa: skip on positive AC - printf( STDERR "PC %06o: spa\n", $PC ) if ($debug); + printf( STDERR "PC %06o: spa AC %06o\n", $PC, $AC ) if ($debug); $PC += ( $AC >= 0 ) ? 2 : 1; return; } if ( $instruction == 0741200 ) { # sna: skip on non-zero AC - printf( STDERR "PC %06o: sna\n", $PC ) if ($debug); + printf( STDERR "PC %06o: sna AC %06o\n", $PC, $AC ) if ($debug); $PC += ( $AC != 0 ) ? 2 : 1; return; } + if ( $instruction == 0740200 ) { # sza: skip on zero AC + printf( STDERR "PC %06o: sza AC %06o\n", $PC, $AC ) if ($debug); + $PC += ( $AC == 0 ) ? 2 : 1; + return; + } printf( STDERR "PC %06o: unknown instruction %08o\n", $PC, $instruction ); exit(1); } @@ -237,14 +314,13 @@ sub sys_open { if ( open( my $FH, "<", $filename ) ) { # Find a place in the @FD array to store this filehandle. 99 is arbitrary - my $fd; - foreach $fd ( 0 .. 99 ) { + foreach my $fd ( 0 .. 99 ) { if ( !defined( $FD[$fd] ) ) { $FD[$fd] = $FH; + $AC = $fd; last; } } - $AC = $fd; return; } else { # No filehandle, so it's an error @@ -393,3 +469,22 @@ sub mem2string { $addr++; } } + +# Given a string and the address of a word in memory, copy +# the string into memory starting at that address and NUL +# terminate the string. Return the first address after the string. +# +# We will go off the end of the string: suppress warnings +no warnings ('substr'); +sub string2mem { + my ($str, $base)= @_; + + # <= length so we go off the end and insert a NUL + for (my $i=0; $i <= length($str); $i += 2) { + my $c1= substr($str, $i, 1) || ""; + my $c2= substr($str, $i+1, 1) || ""; + #printf("Saving %06o to %05o\n", (ord($c1) << 9 ) | ord($c2), $base); + $Mem[$base++]= (ord($c1) << 9 ) | ord($c2); + } + return($base); +} diff --git a/tools/simplecat.s b/tools/simplecat.s index 7d01b49..c156620 100644 --- a/tools/simplecat.s +++ b/tools/simplecat.s @@ -1,6 +1,13 @@ " Simple cat program: echo stdin to stdout until no more words to read main: + " Load the pointer pointer in 017777 to see if we have any arguments + lac 017777 i + sza " No args, so copy stdin to stdout + jmp catfiles + +" This section copies from standard input to standard output +stdinout: " Read 5 words into the buffer from stdin lac d0 sys read; buf; 5 @@ -15,15 +22,81 @@ main: " Write 5 words from the buffer to stdout lac d1 sys write; buf; 1:0 - jmp main -error: + " and loop back for more words to read + jmp stdinout + +" This section opens files, and copies their contents to standard output +catfiles: + " We start with AC pointing to an argument. Save it at label 1f + dac 1f + + " Open the file and get the fd into AC + sys open; 1:0; 0; 0 + spa + jmp noopen " Bad fd, exit with an error message + dac fd " Save the file descriptor + +fileloop: + " Read 5 words into the buffer from the input file + lac fd + sys read; buf; 5 + spa " Skip if result was >= 0 + jmp error " Result was -ve, so error result + sna " Skip if result was >0 + jmp fileend " Result was zero, so nothing left to read + + " Save the count of words read in + dac 1f + + " Write 5 words from the buffer to stdout + lac d1 + sys write; buf; 1:0 + + " and loop back for more words to read + jmp fileloop + +fileend: + " Close the open file descriptor + lac fd + sys close + + " Load and increment the 017777 pointer + lac 017777 + tad d1 + dac 017777 + + " Load the pointer pointer in 017777 to see if we have any more arguments + lac 017777 i + sna " No args, so end the program + jmp end + jmp catfiles " Otherwise loop back to cat this file + end: " exit sys exit +noopen: + " Print an "err open" string and exit + lac d1 + sys write; noopenstr; 5 + sys exit + +noopenstr: + ;;;012000 + +error: + " Print an "err read" string and exit + lac d1 + sys write; noreadstr; 5 + sys exit + +noreadstr: + ;;;012000 + d0: 0 d1: 1 +fd: 0 " fd of the open file " Input buffer for read buf: 0; 0; 0; 0; 0