Java程序辅导

C C++ Java Python Processing编程在线培训 程序编写 软件开发 视频讲解

客服在线QQ:2653320439 微信:ittutor Email:itutor@qq.com
wx: cjtutor
QQ: 2653320439
COMP1521 22T1 — Week 04 Laboratory Sample Solutions COMP1521 - 22T1 Outline Timetable Forum Week 04 Week 01 Week 02 Week 03 Week 04 Week 05 Week 07 Week 08 Week 09 Week 10 Laboratory Tutorial Laboratory Weekly Test Sample Solutions Exercises Sample Solutions Week 04 Laboratory Sample Solutions Objectives learning how function calls are implemented practicing MIPS memory access practicing calculating array indices practicing using MIPS control instructions (branch) practicing running MIPS programs with mipsy and mipsy-web Preparation Before the lab you should re-read the relevant lecture slides and their accompanying examples. Getting Started Set up for the lab by creating a new directory called lab04 and changing to this directory. mkdir lab04 cd lab04 There are some provided files for this lab which you can fetch with this command: 1521 fetch lab04 If you're not working at CSE, you can download the provided files as a zip file or a tar file. Exercise — individual: MIPS 2d array In the files for this lab, you have been given lookup.s, a MIPS assembler program that reads 2 numbers and then prints 42. Add code to lookup.s to make it equivalent to this C program: // Read 2 numbers and use them as indices into a 2d-array #include int array[42][24] = { { 9, 4, 3, 2, 5, 1, 1, 4, 3, 1, 2, 6, 7, 5, 6, 2, 8, 1, 8, 3, 4, 1, 1, 1 }, { 7, 3, 9, 6, 6, 2, 4, 8, 6, 8, 1, 9, 8, 2, 9, 5, 9, 8, 9, 9, 2, 3, 1, 1 }, { 1, 4, 6, 5, 4, 2, 9, 5, 7, 9, 5, 6, 4, 1, 6, 9, 6, 1, 9, 3, 8, 3, 1, 2 }, { 3, 3, 3, 9, 7, 3, 7, 1, 3, 2, 3, 7, 7, 3, 2, 5, 8, 1, 4, 2, 4, 5, 9, 4 }, { 5, 7, 6, 9, 4, 2, 4, 9, 4, 7, 9, 2, 8, 1, 6, 2, 7, 4, 9, 7, 1, 9, 3, 5 }, { 8, 3, 8, 9, 3, 4, 6, 2, 4, 1, 3, 3, 2, 1, 2, 4, 2, 7, 8, 6, 8, 6, 9, 9 }, { 9, 5, 8, 9, 7, 5, 6, 6, 2, 9, 5, 1, 1, 8, 6, 8, 3, 4, 1, 1, 5, 9, 5, 2 }, { 3, 2, 4, 1, 4, 8, 2, 8, 7, 6, 7, 8, 8, 3, 8, 2, 6, 5, 5, 5, 5, 9, 5, 3 }, { 7, 1, 3, 9, 8, 8, 6, 3, 1, 7, 6, 5, 6, 9, 3, 8, 1, 5, 7, 6, 7, 7, 5, 6 }, { 4, 6, 5, 7, 4, 1, 4, 7, 3, 5, 5, 7, 9, 6, 8, 4, 3, 1, 9, 9, 2, 6, 8, 9 }, { 2, 3, 8, 5, 8, 8, 7, 1, 8, 1, 1, 8, 2, 2, 3, 9, 7, 6, 7, 9, 3, 2, 6, 5 }, { 1, 4, 7, 4, 7, 7, 7, 7, 9, 9, 8, 9, 5, 5, 3, 3, 9, 5, 8, 7, 7, 6, 1, 7 }, { 5, 3, 8, 7, 5, 6, 1, 9, 5, 6, 3, 3, 5, 9, 9, 5, 4, 1, 3, 8, 1, 1, 1, 4 }, { 9, 8, 1, 7, 5, 1, 7, 4, 9, 7, 4, 8, 2, 5, 9, 3, 6, 3, 6, 3, 2, 7, 3, 2 }, { 1, 6, 1, 4, 2, 9, 6, 1, 3, 2, 5, 7, 3, 9, 4, 4, 6, 5, 9, 8, 4, 5, 1, 4 }, { 7, 7, 7, 2, 1, 6, 1, 3, 9, 4, 4, 6, 6, 6, 3, 9, 3, 8, 2, 8, 8, 4, 8, 7 }, { 7, 8, 7, 9, 3, 5, 7, 1, 1, 4, 1, 4, 9, 6, 7, 3, 8, 5, 1, 7, 9, 2, 2, 2 }, { 2, 4, 6, 5, 7, 3, 4, 6, 1, 7, 2, 5, 1, 7, 1, 2, 9, 6, 7, 8, 5, 4, 5, 7 }, { 2, 4, 4, 9, 2, 8, 1, 9, 5, 9, 5, 9, 8, 3, 4, 7, 6, 7, 5, 2, 9, 9, 5, 5 }, { 8, 4, 2, 6, 3, 8, 8, 3, 6, 3, 2, 4, 5, 1, 8, 6, 6, 4, 5, 8, 4, 6, 8, 5 }, { 7, 7, 9, 8, 4, 1, 1, 3, 8, 8, 7, 6, 3, 8, 1, 2, 2, 4, 4, 5, 3, 5, 9, 9 }, { 5, 7, 1, 7, 5, 5, 8, 1, 4, 6, 5, 7, 5, 9, 3, 7, 4, 8, 6, 4, 1, 6, 7, 1 }, { 4, 5, 3, 3, 1, 2, 5, 3, 1, 5, 7, 6, 6, 2, 8, 8, 8, 3, 6, 3, 1, 2, 6, 3 }, { 9, 5, 3, 4, 7, 2, 9, 9, 8, 6, 2, 5, 9, 3, 1, 8, 6, 9, 6, 3, 3, 2, 3, 3 }, { 8, 6, 5, 3, 3, 7, 6, 3, 3, 9, 1, 4, 7, 5, 1, 6, 5, 1, 6, 8, 8, 1, 9, 7 }, { 4, 7, 5, 9, 1, 7, 6, 9, 5, 2, 3, 7, 3, 8, 8, 3, 9, 8, 5, 6, 1, 6, 6, 9 }, { 2, 8, 6, 9, 3, 3, 6, 9, 4, 5, 2, 6, 3, 8, 3, 9, 6, 7, 6, 5, 6, 8, 2, 6 }, { 4, 8, 6, 4, 5, 3, 9, 4, 3, 4, 7, 9, 9, 4, 5, 8, 6, 6, 3, 4, 7, 1, 3, 4 }, { 7, 4, 6, 7, 1, 9, 6, 2, 8, 4, 5, 6, 7, 6, 4, 1, 6, 3, 1, 2, 5, 9, 2, 1 }, { 2, 8, 9, 1, 6, 5, 1, 7, 2, 3, 3, 5, 4, 8, 6, 1, 9, 8, 5, 8, 1, 4, 4, 7 }, { 8, 8, 2, 9, 9, 4, 8, 8, 9, 2, 6, 4, 2, 8, 1, 2, 3, 3, 9, 5, 3, 1, 1, 1 }, { 3, 9, 5, 7, 7, 9, 7, 3, 4, 2, 1, 8, 6, 3, 6, 9, 3, 3, 4, 2, 5, 1, 2, 3 }, { 4, 4, 6, 4, 5, 8, 1, 7, 4, 4, 6, 6, 9, 7, 9, 4, 3, 6, 6, 4, 9, 8, 2, 6 }, { 3, 8, 2, 2, 7, 4, 3, 8, 7, 4, 1, 6, 6, 2, 3, 5, 2, 1, 8, 4, 6, 4, 8, 6 }, { 5, 2, 5, 6, 5, 9, 3, 3, 8, 1, 3, 8, 2, 9, 2, 8, 9, 7, 2, 7, 5, 5, 7, 7 }, { 2, 7, 6, 4, 3, 2, 1, 4, 6, 3, 7, 5, 7, 7, 5, 6, 4, 6, 8, 2, 9, 3, 6, 1 }, { 6, 4, 4, 6, 1, 4, 2, 6, 3, 7, 9, 9, 4, 4, 2, 1, 8, 1, 4, 4, 2, 7, 4, 9 }, { 3, 8, 5, 2, 3, 9, 2, 4, 8, 9, 3, 3, 6, 2, 3, 3, 1, 8, 5, 8, 8, 5, 1, 9 }, { 1, 5, 8, 1, 4, 9, 2, 4, 9, 5, 7, 6, 7, 4, 8, 9, 1, 3, 8, 6, 4, 4, 9, 9 }, { 5, 6, 7, 8, 3, 2, 9, 1, 1, 7, 7, 6, 9, 7, 7, 7, 8, 8, 3, 3, 8, 9, 9, 1 }, { 8, 2, 5, 9, 1, 1, 7, 6, 3, 6, 7, 7, 7, 2, 4, 5, 5, 2, 1, 1, 1, 7, 4, 3 }, { 8, 9, 4, 5, 4, 6, 2, 5, 3, 7, 5, 1, 6, 7, 2, 8, 5, 6, 2, 2, 1, 7, 6, 2 }, }; int main(void) { int x, y; printf("Enter x: "); scanf("%d", &x); printf("Enter y: "); scanf("%d", &y); printf("%d\n", array[x][y]); return 0; } In other words, it should read 2 numbers and use them as array indices to print a value from a 2 dimensional array. For example: 1521 mipsy lookup.s Enter x: 5 Enter y: 8 4 1521 mipsy lookup.s Enter x: 41 Enter y: 23 2 1521 mipsy lookup.s Enter x: 0 Enter y: 0 9 The MIPS you given already has suitable directives to create an array equivalent to the one in the C program. Assumptions/Limitations/Clarifications You can assume both numbers read are valid array indices. When you think your program is working, you can use autotest to run some simple automated tests: 1521 autotest lookup When you are finished working on this exercise, you must submit your work by running give: give cs1521 lab04_lookup lookup.s You must run give before Monday 14 March 21:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own. Sample solution for lookup.s # Read 2 numbers and use them as indices into a 2d-array # x in $t0, y in $t1 # $t2..$t7 used for temporary values main: la $a0, prompt_x # printf("Enter x: "); li $v0, 4 syscall li $v0, 5 # scanf("%d", &x); syscall # move $t0, $v0 la $a0, prompt_y # printf("Enter y: "); li $v0, 4 syscall li $v0, 5 # scanf("%d", &y); syscall # move $t1, $v0 mul $t3, $t0, 24 # calculate &array[x][y] add $t4, $t3, $t1 mul $t5, $t4, 4 la $t6, array add $t7, $t6, $t5 lw $a0, 0($t7) # printf("%d", array[x][y]) li $v0, 1 syscall li $a0, '\n' # printf("%c", '\n'); li $v0, 11 syscall li $v0, 0 # return 0 jr $31 .data prompt_x: .asciiz "Enter x: " prompt_y: .asciiz "Enter y: " array: .word 9, 4, 3, 2, 5, 1, 1, 4, 3, 1, 2, 6, 7, 5, 6, 2, 8, 1, 8, 3, 4, 1, 1, 1 .word 7, 3, 9, 6, 6, 2, 4, 8, 6, 8, 1, 9, 8, 2, 9, 5, 9, 8, 9, 9, 2, 3, 1, 1 .word 1, 4, 6, 5, 4, 2, 9, 5, 7, 9, 5, 6, 4, 1, 6, 9, 6, 1, 9, 3, 8, 3, 1, 2 .word 3, 3, 3, 9, 7, 3, 7, 1, 3, 2, 3, 7, 7, 3, 2, 5, 8, 1, 4, 2, 4, 5, 9, 4 .word 5, 7, 6, 9, 4, 2, 4, 9, 4, 7, 9, 2, 8, 1, 6, 2, 7, 4, 9, 7, 1, 9, 3, 5 .word 8, 3, 8, 9, 3, 4, 6, 2, 4, 1, 3, 3, 2, 1, 2, 4, 2, 7, 8, 6, 8, 6, 9, 9 .word 9, 5, 8, 9, 7, 5, 6, 6, 2, 9, 5, 1, 1, 8, 6, 8, 3, 4, 1, 1, 5, 9, 5, 2 .word 3, 2, 4, 1, 4, 8, 2, 8, 7, 6, 7, 8, 8, 3, 8, 2, 6, 5, 5, 5, 5, 9, 5, 3 .word 7, 1, 3, 9, 8, 8, 6, 3, 1, 7, 6, 5, 6, 9, 3, 8, 1, 5, 7, 6, 7, 7, 5, 6 .word 4, 6, 5, 7, 4, 1, 4, 7, 3, 5, 5, 7, 9, 6, 8, 4, 3, 1, 9, 9, 2, 6, 8, 9 .word 2, 3, 8, 5, 8, 8, 7, 1, 8, 1, 1, 8, 2, 2, 3, 9, 7, 6, 7, 9, 3, 2, 6, 5 .word 1, 4, 7, 4, 7, 7, 7, 7, 9, 9, 8, 9, 5, 5, 3, 3, 9, 5, 8, 7, 7, 6, 1, 7 .word 5, 3, 8, 7, 5, 6, 1, 9, 5, 6, 3, 3, 5, 9, 9, 5, 4, 1, 3, 8, 1, 1, 1, 4 .word 9, 8, 1, 7, 5, 1, 7, 4, 9, 7, 4, 8, 2, 5, 9, 3, 6, 3, 6, 3, 2, 7, 3, 2 .word 1, 6, 1, 4, 2, 9, 6, 1, 3, 2, 5, 7, 3, 9, 4, 4, 6, 5, 9, 8, 4, 5, 1, 4 .word 7, 7, 7, 2, 1, 6, 1, 3, 9, 4, 4, 6, 6, 6, 3, 9, 3, 8, 2, 8, 8, 4, 8, 7 .word 7, 8, 7, 9, 3, 5, 7, 1, 1, 4, 1, 4, 9, 6, 7, 3, 8, 5, 1, 7, 9, 2, 2, 2 .word 2, 4, 6, 5, 7, 3, 4, 6, 1, 7, 2, 5, 1, 7, 1, 2, 9, 6, 7, 8, 5, 4, 5, 7 .word 2, 4, 4, 9, 2, 8, 1, 9, 5, 9, 5, 9, 8, 3, 4, 7, 6, 7, 5, 2, 9, 9, 5, 5 .word 8, 4, 2, 6, 3, 8, 8, 3, 6, 3, 2, 4, 5, 1, 8, 6, 6, 4, 5, 8, 4, 6, 8, 5 .word 7, 7, 9, 8, 4, 1, 1, 3, 8, 8, 7, 6, 3, 8, 1, 2, 2, 4, 4, 5, 3, 5, 9, 9 .word 5, 7, 1, 7, 5, 5, 8, 1, 4, 6, 5, 7, 5, 9, 3, 7, 4, 8, 6, 4, 1, 6, 7, 1 .word 4, 5, 3, 3, 1, 2, 5, 3, 1, 5, 7, 6, 6, 2, 8, 8, 8, 3, 6, 3, 1, 2, 6, 3 .word 9, 5, 3, 4, 7, 2, 9, 9, 8, 6, 2, 5, 9, 3, 1, 8, 6, 9, 6, 3, 3, 2, 3, 3 .word 8, 6, 5, 3, 3, 7, 6, 3, 3, 9, 1, 4, 7, 5, 1, 6, 5, 1, 6, 8, 8, 1, 9, 7 .word 4, 7, 5, 9, 1, 7, 6, 9, 5, 2, 3, 7, 3, 8, 8, 3, 9, 8, 5, 6, 1, 6, 6, 9 .word 2, 8, 6, 9, 3, 3, 6, 9, 4, 5, 2, 6, 3, 8, 3, 9, 6, 7, 6, 5, 6, 8, 2, 6 .word 4, 8, 6, 4, 5, 3, 9, 4, 3, 4, 7, 9, 9, 4, 5, 8, 6, 6, 3, 4, 7, 1, 3, 4 .word 7, 4, 6, 7, 1, 9, 6, 2, 8, 4, 5, 6, 7, 6, 4, 1, 6, 3, 1, 2, 5, 9, 2, 1 .word 2, 8, 9, 1, 6, 5, 1, 7, 2, 3, 3, 5, 4, 8, 6, 1, 9, 8, 5, 8, 1, 4, 4, 7 .word 8, 8, 2, 9, 9, 4, 8, 8, 9, 2, 6, 4, 2, 8, 1, 2, 3, 3, 9, 5, 3, 1, 1, 1 .word 3, 9, 5, 7, 7, 9, 7, 3, 4, 2, 1, 8, 6, 3, 6, 9, 3, 3, 4, 2, 5, 1, 2, 3 .word 4, 4, 6, 4, 5, 8, 1, 7, 4, 4, 6, 6, 9, 7, 9, 4, 3, 6, 6, 4, 9, 8, 2, 6 .word 3, 8, 2, 2, 7, 4, 3, 8, 7, 4, 1, 6, 6, 2, 3, 5, 2, 1, 8, 4, 6, 4, 8, 6 .word 5, 2, 5, 6, 5, 9, 3, 3, 8, 1, 3, 8, 2, 9, 2, 8, 9, 7, 2, 7, 5, 5, 7, 7 .word 2, 7, 6, 4, 3, 2, 1, 4, 6, 3, 7, 5, 7, 7, 5, 6, 4, 6, 8, 2, 9, 3, 6, 1 .word 6, 4, 4, 6, 1, 4, 2, 6, 3, 7, 9, 9, 4, 4, 2, 1, 8, 1, 4, 4, 2, 7, 4, 9 .word 3, 8, 5, 2, 3, 9, 2, 4, 8, 9, 3, 3, 6, 2, 3, 3, 1, 8, 5, 8, 8, 5, 1, 9 .word 1, 5, 8, 1, 4, 9, 2, 4, 9, 5, 7, 6, 7, 4, 8, 9, 1, 3, 8, 6, 4, 4, 9, 9 .word 5, 6, 7, 8, 3, 2, 9, 1, 1, 7, 7, 6, 9, 7, 7, 7, 8, 8, 3, 3, 8, 9, 9, 1 .word 8, 2, 5, 9, 1, 1, 7, 6, 3, 6, 7, 7, 7, 2, 4, 5, 5, 2, 1, 1, 1, 7, 4, 3 .word 8, 9, 4, 5, 4, 6, 2, 5, 3, 7, 5, 1, 6, 7, 2, 8, 5, 6, 2, 2, 1, 7, 6, 2 Exercise — individual: MIPS Sieve In the files for this lab, you have been given sieve.s. Add code to sieve.s to make it equivalent to this C program: // Sieve of Eratosthenes // https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes #include #include uint8_t prime[1000]; int main(void) { int i = 0; while (i < 1000) { prime[i] = 1; i++; } i = 2; while (i < 1000) { if (prime[i]) { printf("%d\n", i); int j = 2 * i; while (j < 1000) { prime[j] = 0; j = j + i; } } i++; } return 0; } Use the space in the data area to store the array prime. For example: 1521 mipsy sieve.s 2 3 5 7 11 13 17 19 23 ... 971 977 983 991 997 Use lb and sb instruction to access array prime. You must implement the algorithm in sieve.c. You are not permitted to use another algorithm to print prime numbers. When you think your program is working, you can use autotest to run some simple automated tests: 1521 autotest sieve When you are finished working on this exercise, you must submit your work by running give: give cs1521 lab04_sieve sieve.s You must run give before Monday 14 March 21:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own. Sample solution for sieve.s # i in register $t0 # j in register $t1 # registers $t2, $t3, $t4 used to hold temporary results main: li $t0, 0 # i = 0; loop0: bge $t0, 1000, end0 # while (i < 1000) { la $t2, prime # calculate &prime[i] add $t3, $t2, $t0 # li $t4, 1 sb $t4, ($t3) # prime[i] = 1 add $t0, $t0, 1 # i++; b loop0 # } end0: li $t0, 2 # i = 2; loop1: bge $t0, 1000, done # while (i < 1000) { la $t2, prime # calculate &prime[i] add $t3, $t2, $t0 # lb $t4, ($t3) # load prime[i] into $t3 bne $t4, 1, end2 # if (prime[i]) { move $a0, $t0 # printf("%d", i); li $v0, 1 syscall li $a0, '\n' # printf("%c", '\n'); li $v0, 11 syscall mul $t1, $t0, 2 # j = 2 * i; loop2: bge $t1, 1000, end2 # while (j < 1000) { la $t2, prime # calculate &prime[j] add $t3, $t2, $t1 # sb $0, ($t3) # prime[j] = 0 add $t1, $t1, $t0 # j = j + i; b loop2 # } end2: # } add $t0, $t0, 1 # i++; b loop1 # } done: li $v0, 0 # return 0 jr $31 .data prime: .space 1000 Exercise — individual: MIPS Random Mathematics In the files for this lab, you have been given mathematics.s. Add code to make it equivalent to this C program: void seed_rand(unsigned int); int rand(unsigned int); int add_rand(int); int sub_rand(int); int seq_rand(int); #include int main(void) { int random_seed; printf("Enter a random seed: "); scanf("%d", &random_seed); seed_rand(random_seed); int value = rand(100); value = add_rand(value); value = sub_rand(value); value = seq_rand(value); printf("The random result is: %d\n", value); return 0; } int add_rand(int value) { return value + rand(0xFFFF); } int sub_rand(int value) { return value - rand(value); } int seq_rand(int value) { int limit = rand(100); for (int i = 0; i < limit; i++) { value = add_rand(value); } return value; } //////////////////////// PROVIDED CODE //////////////////////// #define OFFLINE_SEED 0x7F10FB5B int random_seed; // seed the random number generator // with the given seed value void seed_rand(unsigned int seed) { const unsigned int offline_seed = OFFLINE_SEED; random_seed = seed ^ offline_seed; } // return a random number between // 0 and (n - 1) inclusive. // *n must be greater than 0* int rand(unsigned int n) { unsigned int rand = random_seed; rand *= 0x5bd1e995; rand += 12345; random_seed = rand; return rand % n; } For example: 1521 mipsy mathematics.s Enter a random seed: 1 The random result is: 1615324 1521 mipsy mathematics.s Enter a random seed: 44 The random result is: 3601566 1521 mipsy mathematics.s Enter a random seed: 345 The random result is: 455010 You must implement the code in mathematics.s as given mathematics.s. You cannot simplify mathematics.s by removing functions/function calls. The functions seed_rand and rand have been implemented for you. When you think your program is working, you can use autotest to run some simple automated tests: 1521 autotest mathematics When you are finished working on this exercise, you must submit your work by running give: give cs1521 lab04_mathematics mathematics.s You must run give before Monday 14 March 21:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own. Sample solution for mathematics.s .data prompt_str: .asciiz "Enter a random seed: " result_str: .asciiz "The random result is: " .text main: begin push $ra push $s0 la $a0, prompt_str li $v0, 4 syscall li $v0, 5 syscall move $a0, $v0 jal seed_rand li $a0, 100 jal rand move $s0, $v0 move $a0, $s0 jal add_rand move $s0, $v0 move $a0, $s0 jal sub_rand move $s0, $v0 move $a0, $s0 jal seq_rand move $s0, $v0 la $a0, result_str li $v0, 4 syscall move $a0, $s0 li $v0, 1 syscall li $a0, '\n' li $v0, 11 syscall pop $s0 pop $ra end li $v0, 0 jr $ra add_rand: begin push $ra push $a0 li $a0, 0xFFFF jal rand pop $a0 add $v0, $v0, $a0 pop $ra end jr $ra sub_rand: begin push $ra push $a0 jal rand pop $a0 sub $v0, $a0, $v0 pop $ra end jr $ra seq_rand: begin push $ra push $s0 push $s1 push $s2 move $s0, $a0 li $a0, 100 jal rand move $s1, $v0 li $s2, 0 seq_rand__loop_start: bge $s2, $s1, seq_rand__loop_end move $a0, $s0 jal add_rand move $s0, $v0 addi $s2, $s2, 1 b seq_rand__loop_start seq_rand__loop_end: move $v0, $s0 pop $s2 pop $s1 pop $s0 pop $ra end jr $ra ## ## The following are two utility functions, provided for you. ## ## You don't need to modify any of the following. ## But you may find it useful to read through. ## You'll be calling these functions from your code. ## OFFLINE_SEED = 0x7F10FB5B ######################################################################## # .DATA .data # int random_seed; .align 2 random_seed: .space 4 ######################################################################## # .TEXT .text # DO NOT CHANGE THIS FUNCTION seed_rand: # Args: # - $a0: unsigned int seed # Returns: void # # Frame: [] # Uses: [$a0, $t0] # Clobbers: [$t0] # # Locals: # - $t0: offline_seed # # Structure: # seed_rand li $t0, OFFLINE_SEED # const unsigned int offline_seed = OFFLINE_SEED; xor $t0, $a0 # random_seed = seed ^ offline_seed; sw $t0, random_seed jr $ra # return; ######################################################################## # .TEXT .text # DO NOT CHANGE THIS FUNCTION rand: # Args: # - $a0: unsigned int n # Returns: # - $v0: int # # Frame: [] # Uses: [$a0, $v0, $t0] # Clobbers: [$v0, $t0] # # Locals: # - $t0: random_seed # # Structure: # rand lw $t0, random_seed # unsigned int rand = random_seed; multu $t0, 0x5bd1e995 # rand *= 0x5bd1e995; mflo $t0 addiu $t0, 12345 # rand += 12345; sw $t0, random_seed # random_seed = rand; remu $v0, $t0, $a0 # rand % n jr $ra # return rand % n; Exercise — individual: MIPS factorial In the files for this lab, you have been given factorial.s. Add code to make it equivalent to this C program: // Recursive factorial function // n < 1 yields n! = 1 #include int factorial(int); int main(void) { int n = 0; printf("Enter n: "); scanf("%d", &n); int f = factorial(n); printf("%d! = %d\n", n, f); return 0; } int factorial(int n) { int result; if (n > 1) { result = n * factorial(n - 1); } else { result = 1; } return result; } For example: 1521 mipsy factorial.s Enter n: 5 5! = 120 1521 mipsy factorial.s Enter n: 7 7! = 5040 1521 mipsy factorial.s Enter n: 1 1! = 1 You must implement the code in factorial.c as a recursive function. You may not use another algorithm to calculate or print factorials. When you think your program is working, you can use autotest to run some simple automated tests: 1521 autotest factorial When you are finished working on this exercise, you must submit your work by running give: give cs1521 lab04_factorial factorial.s You must run give before Monday 14 March 21:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own. Sample solution for factorial.s # Recursive factorial function # n < 1 yields n! = 1 # $s0 is used for n # we use an s register because the convention is their value # is preserved across function calls # f is in $t0 main: begin # create stack frame push $ra # save $ra push $s0 # save $s0 li $s0, 0 la $a0, msg1 # li $v0, 4 # printf("%s", "Enter n: ") syscall # li $v0, 5 # syscall # scanf("%d", &n) move $s0, $v0 # move $a0, $s0 # jal factorial # factorial(n) move $t0, $v0 # move $a0, $s0 # li $v0, 1 # syscall # printf("%d", n) la $a0, msg2 # li $v0, 4 # printf("%s", "! = ") syscall # move $a0, $t0 # li $v0, 1 # printf("%d", f) syscall # li $a0, '\n' # li $v0, 11 # printf("%c", '\n'); syscall # pop $s0 # restore $s0 pop $ra # restore $ra end # clean up stack frame li $v0, 0 # return 0 jr $ra .data msg1: .asciiz "Enter n: " msg2: .asciiz "! = " # $s0 is used for n # we use an s register because the convention is their value # is preserved across function calls # result is in $t0 .text factorial: begin # create stack frame push $ra # save return address push $s0 # save $s0 move $s0, $a0 ble $s0, 1, else # if (n > 1) { addi $a0, $s0, -1 # result = n * fac(n - 1); jal factorial # mul $t0, $v0, $s0 # j end else: # } else { li $t0, 1 # result = 1 end: # } move $v0, $t0 pop $s0 # restore $s0 pop $ra # restore $ra end # restore sp jr $ra Challenge Exercise — individual: MIPS Ackermann Function In the files for this lab, you have been given ackermann.s. Add code to make it equivalent to this C program: #include int Ackermann(int, int); int main(void) { int m, n; printf("Enter m: "); scanf("%d", &m); printf("Enter n: "); scanf("%d", &n); int f = ackermann(m, n); printf("Ackermann(%d, %d) = %d\n", m, n, f); return 0; } int ackermann(int m, int n) { if (m == 0) return n + 1; if (n == 0) return ackermann(m - 1, 1); return ackermann(m - 1, ackermann(m, n - 1)); } For example: 1521 mipsy ackermann.s Enter m: 0 Enter n: 0 1 1521 mipsy ackermann.s Enter m: 3 Enter n: 1 13 1521 mipsy ackermann.s Enter m: 3 Enter n: 5 253 1521 mipsy ackermann.s Enter m: 4 Enter n: 0 13 The Ackermann Function grows very very quickly And will get very very very slow. Only use very small values for m and n Ackermann(4, 1) takes over an hour to run out of memory. When you think your program is working, you can use autotest to run some simple automated tests: 1521 autotest ackermann When you are finished working on this exercise, you must submit your work by running give: give cs1521 lab04_ackermann ackermann.s You must run give before Monday 14 March 21:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own. Sample solution for ackermann.s .text main: begin push $ra push $s0 push $s1 push $s2 la $a0, prompt_m li $v0, 4 syscall li $v0, 5 syscall move $s0, $v0 la $a0, prompt_n li $v0, 4 syscall li $v0, 5 syscall move $s1, $v0 move $a0, $s0 move $a1, $s1 jal ackermann move $s2, $v0 la $a0, msg1 li $v0, 4 syscall move $a0, $s0 li $v0, 1 syscall la $a0, msg2 li $v0, 4 syscall move $a0, $s1 li $v0, 1 syscall la $a0, msg3 li $v0, 4 syscall move $a0, $s2 li $v0, 1 syscall li $a0, '\n' li $v0, 11 syscall pop $s2 pop $s1 pop $s0 pop $ra end li $v0, 0 jr $ra .data prompt_m: .asciiz "Enter m: " prompt_n: .asciiz "Enter n: " msg1: .asciiz "Ackermann(" msg2: .asciiz ", " msg3: .asciiz ") = " .text ackermann: begin push $ra ackermann__try_m: bnez $a0, ackermann__try_n addi $v0, $a1, 1 b ackermann__end ackermann__try_n: bnez $a1, ackermann__except addi $a0, $a0, -1 li $a1, 1 jal ackermann b ackermann__end ackermann__except: push $a0 addi $a1, $a1, -1 jal ackermann pop $a0 addi $a0, $a0, -1 move $a1, $v0 jal ackermann ackermann__end: pop $ra end jr $ra Challenge Exercise — individual: Polymipsism (Attempt if you dare!) Polymorphism is the ability for a program to use a common interface for different underlying forms. This is a powerful feature of many modern programming languages, and is core to most widely used object-oriented programming languages (eg. Java, C#, Python). As programmers that love a tough challenge, we would like to bring polymorphism to MIPS assembly -- polymipsism! In particular, we would like to implement a simplified model of a specific class of polymorphism: namely, late-binding ad-hoc polymorphism through duck typing. What a mouthful! Let's look at some simple Python code to try to understand how it works: class Duck: def __init__(self, name): self.name = name def speak(self): print(f"{self.name} says quack!") class Dog: def __init__(self, name): self.name = name def speak(self): print(f"{self.name} says woof!") class Cat: def __init__(self, name): self.name = name def speak(self): print(f"{self.name} says meow!") our_animals = [Duck("Daffy"), Dog("Clifford"), Cat("Scruffles")] for animal in our_animals: animal.speak() # This program will output: # Daffy says Quack! # Clifford says Woof! # Scruffles says Meow! The code above defines three animal types: a Duck, a Dog, and a Cat. Each of these types defines a function __init__, which is essentially a special function to say that in order to create something of this type, you are required to provide a name. They each define a function speak, that prints out a specific message. Importantly, the function is named exactly the same: "speak" in each animal. If the functions had even slightly different names, then our polymorphism would not work. We then create a list of these animal "objects" called our_animals, providing each of the animals a name. We can then iterate over this list, and call speak() on each object. Because each of those animals has a function named speak, we can call that speak function on each object without knowing exactly which type of object it is. This practice was named duck typing from the long-time idiom: "If it walks like a duck and it quacks like a duck, then it must be a duck". Aside: if learning about these kinds of programming concepts is something you may be interested in, don't hesitate to check out COMP3161! Unfortunately, we aren't given such convenient language features to use in C (let alone MIPS assembly), so we need to get a bit creative! In particular, we're going to need to make heavy use of function pointers. These can be quite tricky to understand, so make sure you understand the fundamentals before starting on this exercise. Using our polymipsism library, this is how the equivalent C code looks: #include #include "polymipsism.h" #include "provided.h" object make_animal(char *name, void *(*fn_ptr)(void *)); void *duck_speak(void *); void *dog_speak(void *); void *cat_speak(void *); int main(void) { object duck = make_animal("Daffy", duck_speak); object dog = make_animal("Clifford", dog_speak); object cat = make_animal("Scruffles", cat_speak); obj_call(duck, "speak"); obj_call(dog, "speak"); obj_call(cat, "speak"); return 0; } object make_animal(char *name, void *(*fn_ptr)(void *)) { object obj = make_object(name, 1); obj_define(obj, "speak", fn_ptr); return obj; } void *duck_speak(void *data) { printf("%s says quack!\n", (char *) data); return NULL; } void *dog_speak(void *data) { printf("%s says woof!\n", (char *) data); return NULL; } void *cat_speak(void *data) { printf("%s says meow!\n", (char *) data); return NULL; } If you squint a little, you can hopefully see a vague resemblance between the first Python example and our C code's main function. Indeed, running the C code will produce the same output as the Python: dcc provided.c polymipsism.c main_duck.c -o duck_typing ./duck_typing Daffy says quack! Clifford says woof! Scruffles says meow! Also provided is main_simple.c (and main_simple.s) which is a simple usage of the polymipsism library, only taking advantage of the dynamic dispatch it provides. dcc provided.c polymipsism.c main_simple.c -o simple ./simple 10 Your task is to translate the polymipsism library from C to MIPS -- i.e. you do not have to translate any main functions. You are given some provided files to help you with this task: polymipsism.c the code you will translate to MIPS assembly polymipsism.s your starter file: your code goes here main_duck.c a polymorphism example -- the C code seen above main_duck.s main_duck.c translated to MIPS assembly main_simple.c another polymorphism example main_simple.s main_simple.c translated to MIPS assembly provided.c C functions that have already been translated for you provided.s provided.c translated to MIPS assembly There is also a couple of header files to glue everything together: polymipsism.h the header file for the polymipsism library provided.h the header file for the provided functions You should read through all these files before starting on this exercise.   To test your code using mipsy: 1521 mipsy constants.s provided.s main_simple.s polymipsism.s 10 1521 mipsy constants.s provided.s main_duck.s polymipsism.s Daffy says quack! Clifford says woof! Scruffles says meow! The C code in this exercise has some very scary types, especially when it comes to function pointers. In this particular exercise, you can mostly ignore the C types, as they almost all end up as simply a 4 byte value (i.e. word) in MIPS. Our reference solution is approximately 120 instructions. Your solution may be shorter or longer than this, but you may consider this as a guideline when deciding whether to attempt this exercise or not. This exercise is deliberately quite difficult, and plays with some tricky concepts that are challenging to express in C - even more so in assembly. Don't be discouraged if you can't get this one right, and please ask questions on the course forum to clarify any doubts you may have! When you think your program is working, you can use autotest to run some simple automated tests: 1521 autotest polymipsism When you are finished working on this exercise, you must submit your work by running give: give cs1521 lab04_polymipsism polymipsism.s You must run give before Monday 14 March 21:00 to obtain the marks for this lab exercise. Note that this is an individual exercise, the work you submit with give must be entirely your own. Sample solution for polymipsism.s .data err_full_object_str: .asciiz "error: tried to add fn to full object\n" err_find_fn_str: .asciiz "error: could not find function\n" .text make_object: make_object__prologue: begin push $ra push $s0 push $s1 push $s2 make_object__body: move $s0, $a0 move $s1, $a1 move $a0, $s1 jal object_size move $a0, $v0 jal bumpalo move $s2, $v0 move $a0, $s2 jal obj_data sw $s0, ($v0) move $a0, $s2 jal obj_capacity sw $s1, ($v0) move $a0, $s2 jal obj_len li $t0, 0 sw $t0, ($v0) move $v0, $s2 make_object__epilogue: pop $s2 pop $s1 pop $s0 pop $ra end jr $ra obj_define: obj_define__prologue: begin push $ra push $s0 # obj push $s1 # fn_name push $s2 # fn_ptr push $s3 # fn_capacity push $s4 # fn_len obj_define__body: move $s0, $a0 move $s1, $a1 move $s2, $a2 jal obj_capacity lw $s3, ($v0) move $a0, $s0 jal obj_len lw $s4, ($v0) blt $s4, $s3, obj_define__else li $v0, 4 la $a0, err_full_object_str syscall li $v0, 17 li $a0, 1 syscall obj_define__else: move $a0, $s0 move $a1, $s4 jal obj_nth_fn_name sw $s1, ($v0) move $a0, $s0 move $a1, $s4 jal obj_nth_fn_ptr sw $s2, ($v0) move $a0, $s0 jal obj_len addi $t0, $s4, 1 sw $t0, ($v0) move $v0, $s0 obj_define__epilogue: pop $s4 pop $s3 pop $s2 pop $s1 pop $s0 pop $ra end jr $ra obj_call: obj_call__prologue: begin push $ra push $s0 # obj push $s1 # fn push $s2 # len push $s3 # i push $s4 # fn_ptr obj_call__body: move $s0, $a0 move $s1, $a1 jal obj_len lw $s2, ($v0) obj_call__for_init: li $s3, 0 obj_call__for_cond: blt $s3, $s2, obj_call__for_body b obj_call__for_post obj_call__for_body: move $a0, $s0 move $a1, $s3 jal obj_nth_fn_name lw $a0, ($v0) move $a1, $s1 jal streq beqz $v0, obj_call__for_step move $a0, $s0 move $a1, $s3 jal obj_nth_fn_ptr lw $s4, ($v0) move $a0, $s0 jal obj_data lw $a0, ($v0) jalr $s4 b obj_call__epilogue obj_call__for_step: addi $s3, 1 b obj_call__for_cond obj_call__for_post: li $v0, 4 la $a0, err_find_fn_str syscall li $v0, 17 li $a0, 1 syscall obj_call__epilogue: pop $s4 pop $s3 pop $s2 pop $s1 pop $s0 pop $ra end jr $ra Submission When you are finished each exercises make sure you submit your work by running give. You can run give multiple times. Only your last submission will be marked. Don't submit any exercises you haven't attempted. If you are working at home, you may find it more convenient to upload your work via give's web interface. Remember you have until Week 5 Monday 21:00:00 to submit your work. You cannot obtain marks by e-mailing your code to tutors or lecturers. You check the files you have submitted here. Automarking will be run by the lecturer several days after the submission deadline, using test cases different to those autotest runs for you. (Hint: do your own testing as well as running autotest.) After automarking is run by the lecturer you can view your results here. The resulting mark will also be available via give's web interface. Lab Marks When all components of a lab are automarked you should be able to view the the marks via give's web interface or by running this command on a CSE machine: 1521 classrun -sturec COMP1521 22T1: Computer Systems Fundamentals is brought to you by the School of Computer Science and Engineering at the University of New South Wales, Sydney. For all enquiries, please email the class account at cs1521@cse.unsw.edu.au CRICOS Provider 00098G