Assignment 3 solution

Part of the homework for 22C:50, Summer 2004
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

  1. Write an EAL program that demonstrates the different forms of expressions supported by the EAL assembler distributed as MP0. To do this, you'll need to read the expression parser in parser.c.
         1             |; demo of types of expressions (<operand>)
         2             |
         3             |IDENT = 1     ; an identifier for demo purposes
         4             |
         5             |; forms of terms, note that <operand> ::= <term>
         6 0000: 0001  |      W IDENT            ; <term> ::= <identifier>
         7 0002: 0063  |      W 99               ; <term> ::= <number>
         8 0004: 0004  |      W .                ; <term> ::= .
         9             |
        10             |; forms of expressions, note that <term> ::= IDENT
        11 0006: 0001  |      W IDENT            ; <operand> ::= <term>
        12 0008: 0002  |      W IDENT + IDENT    ; <operand> ::= <term> { + <term> }
        13 000A: 0003  |      W IDENT + IDENT + IDENT
        14 000C: 0004  |      W IDENT + IDENT + IDENT + IDENT
        15             |
        16             |; permissible operators
        17 000E: 0002  |      W IDENT + IDENT   ; ::= <term> { (+|-|&||) <term> }
        18 0010: 0000  |      W IDENT - IDENT
        19 0012: 0001  |      W 99 & IDENT      ; note, 99 and 1 is 1
        20 0014: 0063  |      W 99 | IDENT      ; note, 99 or 1 is 99
        21             |
        22             |; parentheses (not in the BNF, but in parse_operand)!
        23 0016: 0001  |      W (IDENT)
        24 0018: 0002  |      W IDENT + (IDENT)
        25 001A: 0002  |      W (IDENT) + IDENT
        26 001C: 0002  |      W (IDENT + IDENT)
        27             |
        28             |; some illustrations of operator precidence and parens
        29 001E: 0005  |      W    1 + 2 - 3 & 4 | 5    ; = 5
        30 0020: 0005  |      W (((1 + 2)- 3)& 4)| 5    ; = 5
        31 0022: 0002  |      W    1 +(2 -(3 &(4 | 5))) ; = 2
        32 0024: 0002  |      W   (1 + 2)-(3 &(4 | 5))  ; = 2
        33 0026: 0000  |      W  ((1 + 2)- 3)&(4 | 5)   ; = 0
        34             |
        35             |; contexts for expressions
        36 0028: 02    |      B IDENT + 1
        37 0029: 0003  |      W IDENT + 2
        38             |IDENT = IDENT + 3
    

  2. Do problem 4 at the end of Chapter 2 of the notes. This asks for support for multiple labels on a line.

    a) Modified EBNF grammar from Figure 2.9

    We need to change only one rule of this grammar, from
    <statement> ::= [ <identifier> : ] [ ( B | W ) <operand> ]
    to
    <statement> ::= { <identifier> : } [ ( B | W ) <operand> ]

    b) Modified parser from Figure 2.16

    Again, the change required is very small; we replace an if statement with a while loop:

              /* parse optional label */
              while (!strcmp(lex.next,":")) {
                   lex_scan(); /* skip over identifier */
                   lex_scan(); /* skip over colon */
              }
    
    c) Modified parser with graceful error handling:
              /* parse optional label */
              while (!strcmp(lex.next,":")) {
                   if (!is_identifier(lex.this)) {
                        error("label must be identifier");
                   }
                   lex_scan(); /* skip over identifier or error */
                   lex_scan(); /* skip over colon */
              }
    

    Here is an alternate solution that will force malformed labels to be reported as "unexpected opcode" errors.

              /* parse optional label */
              while (is_identifier(lex.this)
              &&     !strcmp(lex.next,":")      ) {
                   lex_scan(); /* skip over identifier */
                   lex_scan(); /* skip over colon */
              }
    
  3. Do problem 5 at the end of Chapter 2 of the notes.

    There are two fairly obvious ways to do this, one using arithmetic, and the other using logic and bit manipulation. Both of these work identically in Java, C and C++. The solutions given here work for unsigned integers. If negative values are to be held, there is more work required in both cases.

    	first_byte = value / 256
    	second_byte = value % 256
    
    	first_byte = value >> 8
    	second_byte = value & 255