P&H 3.2

	add	$a1, $a1, $a1
	add	$a1, $a1, $a1		# multiply $a1 (array size) by 4 (from word to byte)
	add	$v0, $zero, $zero	# represents max count of elems
	add	$t0, $zero, $zero	# represents an array index k
outer:	add	$t4, $a0, $t0		# for (k=0; k<5000; k++) {
	lw	$t4, 0($t4)		#   elem1 = a[k];
	add	$t5, $zero, $zero	#   // represents occurrence count of elem1
	add	$t1, $zero, $zero	#   // represents an array index j
inner:	add	$t3, $a0, $t1		#   for (j=0, count=0; j<5000; j++) {
	lw	$t3, 0($t3)		#     elem2 = a[j];
	bne	$t3, $t4, skip		#     if (elem1 == elem2) {
	addi	$t5, $t5, 1		#       count++;
skip:	addi	$t1, $t1, 4		#     }
	bne	$t1, $a1, inner		#   }
	slt	$t2, $t5, $v0		#   if (count >= maxCount) {
	bne	$t2, $zero, next
	add	$v0, $t5, $zero		#     maxCount = count;
	add	$v1, $t4, $zero		#     mostCommonElem = elem1;
next:	addi	$t0, $t0, 4		#   }
	bne	$t0, $a1, outer		# }

Thus $v1 ends up with the most commonly occurring element in the array, and $v0 ends up with the number of times that element occurs in the array.

P&H 3.6

loop: lw   $v1,0($a0)       #Read next word form the source
      sw   $v1,0($a1)       #Write to destination
      addi $a0,$a0,4        #Advanced pointer to the next word
      addi $a1,$a1,4        #Advance pointer to the next word
      beq  $v1,$zero, exit  #If the word copied = zero exit
      addi $v0,$v0,1        #increment count word copied
      j    loop
exit:

P&H 3.7

All the instructions are I-format.
Here are the field values:
	instr		opcode	rs	rt    immed
	lw $v1,0($a0)	  35	4	3	0
	addi $v0,$v0,1	   8	2	2	1
	sw $v1,0($a1)	  43	5	3	0
	addi $a0,$a0,1	   8	4	4	1
	addi $a1,$a1,1	   8	5	5	1
	bne $v1,$0,loop	   5	3	0	-6

P&H 3.8

int count;
int* source;
int* destination;

[...]

for (count=0; source[count] != 0; count++)
 {
     destination[count] = source[count];
     
 };

P&H 3.9

We assume that i, j, and k correspond to registers $s3, $s4, and $s5, and that the base address of the save array is in $s6.
First, we replace i by $s6+4*i and j by 4*j:
	muli	$s3,$s3,4	# can also do this with two adds
	add	$s3,$s6,$s3
	muli	$s4,$s4,4
Here's the last part of the loop:
	lw	$t0,0($s3)	# load save[i]
	beq	$t0,$s5,repeat	# not branching means loop is done
The update of i must therefore occur prior to that code:
repeat:	add	$s3,$s3,$s4	# represents i = i+j
				# really addr(save[i]) = addr(save[i+j])
And we need to jump over that update to i initially. Here's the complete code segment.
	muli	$s3,$s3,4	# can also do this with two adds
	add	$s3,$s6,$s3
	muli	$s4,$s4,4
	j	load
repeat:	add	$s3,$s3,$s4
	lw	$t0,0($s3)	# load save[i]
	beq	$t0,$s5,repeat	# not branching means loop is done

The code on page 127 executes 10*7+5 = 75 instructions for ten loop iterations.
The optimized code executes 3+10*3 = 33 instructions for ten loop iterations.

P&H 3.10

pseudoinstruction MIPS instruction sequence
move $t5,$t3 add $t5,$t3,$0
clear $t5 add $t5,$0,$0
li $t5,small addi $t5,$0,small
li $t5,big lui $t5,top half of big
ori $t5,$t5,lower half of big
lw $t5,big($t3) lui $at,top half of big
ori $at,bottom half of big
add $at,$at,$t3
lw $t5,0($at)
addi $t5,$t3,big lui $at,top half of big
ori $at,bottom half of big
add $t5,$t3,$at
beq $t5,small,L addi $at,$0,small
beq $t5,$at,L
beq $t5,big,L lui $at,top half of big
ori $at,bottom half of big
beq $t5,$at,L
ble $t5,$t3,L slt $at,$t3,$t5
beq $at,$0,L # $at = 1 if $t5>$t3, = 0 if $t5<=$t3
bgt $t5,$t3,L slt $at,$t3,$t5
bne $at,$0,L
bge $t5,$t3,L slt $at,$t5,$t3
beq $at,$0,L # $at = 1 if $t5<$t3, = 0 if $t5>=$t3
1