Computer Science 3 - 2012 - Test on Week 20 - Solutions

1. I have a memory like my friend Eratosqenes and his sief and cannot remember - remind me of your name (surname) and student number [1]

Pat Terry 63T0884

2. In the prac you were invited to note that sequences like

         LDA   X          and   LDA   Y
         LDV                    <code>
                                STO

occurred so frequently that it might be worth introducing special opcodes LDL X and STL Y instead. By now you will recognise something of the Terry perversity - maybe the machine is defined to have LDA, LDV and STO opcodes rather than simply having only LDL and STL opcodes for no other reason than that it makes for lots of fun late at night to add these opcodes to the machine. But maybe not? If you have LDL and STL, could you completely remove LDA, LDV and STO from the opcode list, or would you still need to have them available? Justify your answer. [2]

If every LDV was preceded by an LDA one could get away with using LDL instead of LDA + LDV, and if every other use of LDA was followed by a STO one could get away without LDA. But this is not the case. Consider the following code:

           read(i); list[i] = list[j];

which, even if we use every LDL and STL we can, translates to

           LDA   i
           INPI         ; read(i)
           LDL   list
           LDL   i
           INXA         ; address of list[i]
           LDL   list
           LDL   j
           INXA         ; address of list[j]
           LDV          ; value of list[j]
           STO          ; list[i = list[j]

3. Translate the following program into PVM code, making use of the INC, LDL and STL opcodes.

     void main () {
       int i;
       bool[] odd = new bool[1000];
       for (i = 0; i < 1000; i++) odd[i] = i % 2 != 0;
     }

Two solutions are given. The one on the left is a literal translation, that on the right is slightly optimized, taking advantage of the fact that a "mod 2" operation yields a 1 for odd numbers, which happens also to be the representation of true. Some submissions showed that their authors are uncomfortable with Boolean assignments.

    0 DSP   2      int i; bool[] odd              0 DSP   2      int i; bool[] odd
    2 LDC   1000                                  2 LDC   1000
    4 ANEW                                        4 ANEW
    5 STL   1      odd = new bool[1000]           5 STL   1      odd = new bool[1000]
    7 LDC   0                                     7 LDC   0
    9 STL   0      i = 0;                         9 STL   0      i = 0;
   11 LDL   0                                    11 LDL   0
   13 LDC   1000                                 13 LDC   1000
   15 CLT                                        15 CLT
   16 BZE   37     while (i < 1000) {            16 BZE   34     while (i < 1000) {
   18 LDL   1                                    18 LDL   1
   20 LDL   0                                    20 LDL   0
   22 LDXA                                       22 LDXA
   23 LDL   0                                    23 LDL   0
   25 LDC   2                                    25 LDC   2
   27 REM                                        27 REM
   28 LDC   0                                    28 STO             odd[i] = i % 2 != 0;
   30 CNE                                        29 LDA   0
   31 STO             odd[i] = i % 2 != 0;       31 INC             i++;
   32 LDA   0                                    32 BRN   11     }
   34 INC             i++;                       34 HALT
   35 BRN   11     }
   37 HALT

4. The following represents a Java translation of the encoding method that you (should have) translated to PVM code in this practical.

     public static void main(String[] args) {
     // rot13 encryption of a text terminated with a period
     // P.D. Terry, Rhodes University, 2012

       char ch;
       do {
         ch = IO.readChar();
         ch = Character.toLowerCase(ch);
         if (Character.isLetter(ch)) ch = (char) ('a' + (ch - 'a' + 13) % 26);
         IO.write(ch);
       }
       while (ch != '.');
     } // main

(a) How would you decode a text that had been supplied to you after being encrypted in this way? [2]

You could simply use the program "as is", since the algorithm is symmetric. However, you would lose the distinction between upper and lower case in the original. If this were really important, code like the following would be better for the encoding/decoding program:

     public static void main(String[] args) {
     // rot13 encryption of a text terminated with a period
     // P.D. Terry, Rhodes University, 2012

       char ch;
       do {
         ch = IO.readChar();
         if      (Character.isUpperCase(ch)) ch = (char) ('A' + (ch - 'A' + 13) % 26);
         else if (Character.isLowerCase(ch)) ch = (char) ('a' + (ch - 'a' + 13) % 26);
         IO.write(ch);
       }
       while (ch != '.');
     } // main

(b) You will note the presence of the (char) cast in this source code. Given that characters are simply represented by integer values at the machine level, and that Java permits you to add character literals to integers in any case (as you can also see exemplified here), what purpose (if any) does the (char) casting operation serve? Could it simply have been omitted? Discuss. [3]

The rules of Java demand that when "arithmetic" is done on "characters" the 16-bit character values are promoted to 32-bit integer values, and the resulting expression is thus normally of int type. The cast serves two purposes - to demote the value from 32 to 16 bits (which may result in a loss of precision, though for examples like the one shown here this should not happen) and to mark the expression as being of char type, and thus assignment compatible to a char designator like ch. This second consideration makes the cast obligatory in this example.

There were a few misconceptions. An assignment - even if it were acceptable - like

         char ch = 'a' + (ch - 'a' + 13) % 26; 

could not change the type of the variable ch to int, even though the type of the expression

         'a' + (ch - 'a' + 13) % 26 

would be int. So the statement

         IO.write(ch); 

does not need another cast. The IO.write method is, indeed, overloaded, but the system will "pick" the version that outputs a character if (as here) the argument (ch) is of the char type.

Curiously, Java will (very sloppily) allow you to code

         char ch = 'a' + 3;     // both terms are constant 

but it will not allow

         char ch1 = ch + 'a';   // one term is a variable 

One rather wishes that the rules for "mixing" types were a bit more self-consistent. C# will not allow either of those statements - and Pascal and Modula-2 would never have let you "get away" with them either!

(c) When you translated the algorithm to PVM code you may (or may not) have added an opcode to perform the casting operation, which seems, in a sense, to be superfluous. After reflection, would such an opcode be a good idea, and if so, can you suggest how the interpreter "case arm" would deal with it? [3]

Since the PVM treats all data values as 32 bit integers, it would appear that no opcode is really needed. However, since Parva uses an ASCII character subset, for which only values 0 .. 255 have any meaning, it would be safer to introduce a CHR opcode that could have an interpretation on the lines of

     case PVM.chr:
       if (mem[cpu.sp] < 0 || mem[cpu.sp > maxChar) ps = badVal;
       break;

5. Here is another algorithm that should be familiar:

     void main() {
     // Read a sequence of digit characters and convert
     // this to the corresponding integer
       int n = 0;
       char ch;
       read(ch);
       while (isDigit(ch)) {
         n = 10 * n + digitValue(ch);
         read(ch);
       }
       write(n);
     } // main

In the practical you (should have) introduced opcodes to achieve the effect of character handling functions lowerCase() and isLetter().

(a) What changes would you have to make to the switch statement in the PVM emulator in the Assembler system you have been using, to support additional opcodes that achieve the effect of character handling functions isDigit() and digitValue()? [3]

          case PVM.dig:            // digitValue
            tos = pop();
            if (Character.isDigit((char) tos) push(tos - '0');
            else ps = badVal;
            break;
          case PVM.isdig:          // isDigit
            tos = pop();
            push(Character.isDigit((char) tos) ? 1 : 0);
            break;

(b) Would you have to make any other changes to the PVM.java file and PVMAsm file to support these extensions? Explain your thinking! [2]

We simply add DIG and ISDIG to the list of opcode/string pairs at the end of the PVM.java file, and add lines giving the numeric equivalent to the list near the beginning. Since these are one-word opcodes, no other changes are needed (in contrast to the addition of codes like STL N and LDL N).

(c) Translate the algorithm above into PVM code, making use of your new opcodes, and also of the STL and LDL opcodes discussed in question 2. (Hint: this can be done in under 20 lines.) [6]

Since most students have an aversion to comments in code, I have left them out...

            0  DSP   2                      0  DSP   2
            2  LDC_0                        2  LDC_0
            3  STL_0                        3  STL_0
            4  LDA_1                        4  LDA_1
            5  INPC                         5  INPC
            6  LDL_1                        6  LDL_1
            7  ISDIG                        7  ISDIG
            8  BZE   22                     8  BZE   20
           10  LDC   10                    10  LDC   10
           12  LDL_0                       12  LDL_0
           13  MUL                         13  MUL
           14  LDL_1                       14  LDL_1
           15  DIG                         15  DIG
           16  ADD                         16  ADD
           17  STL_0                       17  STL_0
           18  LDA_1                       18  BRN   4
           19  INPC                        20  LDL_0
           20  BRN   6                     21  PRNI
           22  LDL_0                       22  HLT
           23  PRNI
           24  HLT


Home  © P.D. Terry