Assignment 5, due Feb 20

Solutions

Part of the homework for CS:2630, Spring 2015
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

  1. Background: The mp1test program could have looked something like this if it were written in the C language:
        /* mp1test.c */
        #include <monitor.h>
    
        typedef struct { /* definition of the record type */
            char * text; /* pointer to the start of the text string */
            int16t x;    /* the X coordinate */
            int16t y;    /* the Y coordinate */
        } record;
    
        /* linkage to the array of pointers to records in mp1.a */
        extern record * array[]
    
        main() {
            int i = 0;
            while (array[i] != NULL) {
                putat( array[i]->x, array[i]->y );
                puts( array[i]->text );
                i = i + 1;
            }
        }
    

    You are not expected to know C, but most of the above syntax should look natural. The following notes about pointers in C may help:

    1. The declaration record * x declares x to be of type "pointer to an object of type record."
    2. The expressio x->y means "given that x is a pointer to an object of some type, use the field named y of that object.

    In the following, assume that this SMAL declaration for the symbol ARRAY has already been given. It allows the linker to link the symbol ARRAY here to the value it was given in the solution to MP1 with which the test program is linked:

        EXT     ARRAY
    

    Assume that register R8 is used for the variable i and note that each array element occupies 4 consecutive bytes; that is, the address of array element array[i] is the address of the first element of the array (array[0]) plus 4 times the value of i. Here, we use the notation array as C code, where the corresponging definition in SMAL is ARRAY.

    a) Write SMAL Hawk code to compute the address of the array element array[i] in register R9. (0.4 points)

    ; a stupid but effective solution
            LIL     R9,ARRAY
    	ADD	R9,R8,R9
    	ADD	R9,R8,R9
    	ADD	R9,R8,R9
    	ADD	R9,R8,R9
    
    ; a faster solution
            LIL     R9,ARRAY
    	ADD	R10,R8,R8       ; R10 = 2*R8
    	ADD	R10,R10,R10     ; R10 = 2*R10
    	ADD	R9,R9,R10
    

    b) Given that the address of array[i] in register R9, write SMAL Hawk code to load the value of array[i] in R10. The value of array[i] is a pointer to a record. (0.4 points)

            LOADS   R10,R9
    

    c) Given that the value of array[i] is in R10, write SMAL Hawk code to check if this value is null, and if so, branch to the label DONE. (0.4 points)

    ; an obvious solution
            CMPI    R10,NULL
            BEQ     DONE
    
    ; a faster solution that works if NULL is zero
            TESTR   R10
            BZS     DONE
    
    ; The fastest solution
            LOADSCC R10,R9  ; an alternate solution to part b)
            BZS     R10
    

    d) Given that R10 points to one record, that is, R10 holds the value of array[i], write SMAL Hawk code to load the value of the text field of that record (array[i]->text) into R3. That value is a pointer to a piece of text. (0.4 points)

    ; what should be the obvious solution
            LOAD    R3,R10,TEXT
    
    ; there are other solutions
            ADDI    R11,R10,TEXT
            LOADS   R3,R11
    
    ; but there is an optimal solution
            LOADS   R3,R10  ; the text field starts at displacement zero
    

    e) Given that a pointer to the text has already been loaded in R3, write SMAL Hawk code to call the Hawk monitor puts() routine. This completes the coding of puts(array[i]->text). (0.4 points)

    ; solved in the style of Chapter 5
            LOADS   R1,PUTS
            JSRS    R1,R1
    
    ; solved in the general but sub-optimal style of Chapter 6
            ADDI    R2,R2,ARSIZE
            LOADS   R1,PUTS
            JSRS    R1,R1
            ADDI    R2,R2,-ARSIZE
    

    Note: This does not go so far as giving the entire mp1test.a because we have not discussed how to work with halfwords on the Hawk machine. That will have to wait until early March.

  2. Background: In problem 1 above, and in Chapter 5 in general, we assumed that the main program could safely use R8 to R15 for variables.

    A question: How does the main program violate the rules for the standard Hawk calling sequence? (0.5 points)

    The rules state that the called routine "may destroy the contents of registers R3 through R7, and all are required to leave R8 through R15 unchanged when the routine returns."

    Main programs written in the style of Chapter 5 use R8 to R15 without saving and restoring their previous values.

  3. All of the examples in Chapter 5 show calls to Hawk monitor routines that look like this:
            LIL     R1,PUTCHAR
            JSRS    R1,R1           ;   putchar( ch )
    

    All of the examples in Chapter 6 show the same call looking like this:

            ADDI    R2,R2,ARSIZE
            LIL     R1,PUTCHAR
            JSRS    R1,R1           ;   putchar( ch )
            ADDI    R2,R2,-ARSIZE
    

    A question: How did Chapter 5 hide the ARSIZE issue from the novice programmer? (0.5 points)

    The skeleton of the main program given in Chapter 5 included

            ADDI    R2,R2,ARSIZE
    

    in the boilerplate before the body of the code, and it included

            ADDI    R2,R2,-ARSIZE
    

    in the boilerplate after the body of the code. So long as the code does not reference local variables in RAM (a subject that is not introduced until Chapter 6), the the code will work.