-------------------------
    Examples of Assembly Code 
    -------------------------

    Here are the examples that I did in class, and a few that
    I did not get to.  This should give you a pretty good idea
    how one accomplishes things in assembly code.

    Prof. Jacob


	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	if (a == b) {
	    c = a;
	    d = b;
	}

	in general, if-then statements are similar
	to saying "if the following is NOT true, then
	skip over these instructions"

		lw	1, 0, a		# r1 <- a
		lw	2, 0, b		# r2 <- b
		bne	1, 2, next	# if (a != b) skip to next
		sw	1, 0, c		# c = a
		sw	2, 0, d		# d = b
	next:	...

	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	if (a != b) {
	    c = a;
	    d = b;
	}

	in general, if-then statements are similar
	to saying "if the following is NOT true, then
	skip over these instructions"

		lw	1, 0, a		# r1 <- a
		lw	2, 0, b		# r2 <- b
		bne	1, 2, then	# if (a != b) skip to then
		jump	next		# requires unconditional jump
	then:	sw	1, 0, c		# c = a
		sw	2, 0, d		# d = b
	next:	...

	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	if (a >= 0) {
	    b = a;
	}

	how can we do this?  2's complement => 
	neg. numbers have 1 in top bit.  if we
	nand with a 1 in the top bit we have
	the following:

	    01111111 => negative
	    11111111 => zero or positive

		lw	1, 0, a		# r1 <- a
		lui	2, 0x8000	# r2 <- 1000 0000
		nand	3, 1, 2		# r3 <- a NAND 10000000
		addi	2, 0, -1	# r2 <- 1111 1111
		bne	3, 2, next	# if (a < 0) skip to next
		sw	1, 0, b		# b = a
	next:	...

	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	if (a >= 0) {
	    b = -a;
	}

	how to change the sign of a number in 2's
	complement?  flip the bits and add 1.  nand-ing
	the number with itself flips the bits.

		lw	1, 0, a		# r1 <- a
		lui	2, 0x8000	# r2 <- 1000 0000
		nand	3, 1, 2		# r3 <- a NAND 10000000
		addi	2, 0, -1	# r2 <- 1111 1111
		bne	3, 2, next	# if (a < 0) skip to next
		nand	1, 1, 1		# r1 <- a NAND a (flips bits)
		addi	1, 1, 1		# r1 <- -a (adds one to the complement)
		sw	1, 0, b		# b = -a
	next:	...

	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	if (a == b) {
	    c++;
	} else {
	    d = a + b;
	}

	it is helpful to think about complex control
	statements as a bunch of labeled blocks:

	    if !x goto B

	    A: --------------
	       |            |
	       |            |
	       --------------
	       goto C

	    B: --------------
	       |            |
	       |            |
	       --------------
	    
	    C: continue ...

	in the code from here on in, i put blank lines
	to separate the conceptual blocks of code -- this
	is just for readability.  most assemblers will
	allow blank lines, but yours does not have to.


		lw	1, 0, a		# r1 <- a
		lw	2, 0, b		# r2 <- b
		bne	1, 2, aNEb	# if (a != b) skip to aNEb

	aEQb:	lw	1, 0, c		# r1 <- c
		addi	1, 1, 1		# c += 1
		sw	1, 0, c		# store c
		jump	next		# (assumes unconditional jump)

	aNEb:	add	1, 1, 2		# r1 <- a + b
		sw	1, 0, d		# d = a + b

	next:	...

	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	while (a != b) {
	    a *= 4;
	}

	here is a loop, and we can either label the
	top & bottom of the loop, or we can put the
	numbers into the bne instructions directly.

	label the loop:

		lw	1, 0, a		# r1 <- a
		lw	2, 0, b		# r2 <- b
		bne	1, 2, loop	# if (a != b) enter loop
		jump	out		# otherwise exit loop
	loop:	add	1, 1, 1		# a*=2
		add	1, 1, 1		# a*=4
		bne	1, 2, loop	# if (a != b) continue loop
	out:	...

	use absolute numbers:

		lw	1, 0, a		# r1 <- a
		lw	2, 0, b		# r2 <- b
		bne	1, 2, 1		# if (a != b) enter loop
		jump	out		# otherwise exit loop
		add	1, 1, 1		# a*=2
		add	1, 1, 1		# a*=4
		bne	1, 2, -3	# if (a != b) continue loop
		...

	note: why do we put the first two loads
	and two conditional branches outside the loop?

	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	do {
	    a *= 4;
	} while (a != b);

	note that the block of instructions is always
	executed at least once; the test happens after
	the first execution.

		lw	1, 0, a		# r1 <- a
		lw	2, 0, b		# r2 <- b
	loop:	add	1, 1, 1		# a*=2
		add	1, 1, 1		# a*=4
		bne	1, 2, loop	# if (a != b) continue loop
		...

	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	if (a < b) {
	    b = -a;
	} else if (a > b) {
	    a = -b
	} else {
	    c++;
	}

	how to do less-than?  well, we can subtract
	one from the other and see if the result is
	negative (just like the earlier example).

		lw	1, 0, a		# r1 <- a
		lw	2, 0, b		# r2 <- b
		bne	1, 2, notequal	# if (a == b) skip to equal

	equal:	lw	1, 0, c		# r1 <- c
		addi	1, 1, 1		# c += 1
		sw	1, 0, c		# store c
		jump	next

     notequal:	nand	2, 2, 2		# r2 <- b NAND b (flips bits)
		addi	2, 2, 1		# r2 <- -b
		add	3, 1, 2		# r3 <- a - b
		lui	4, 0x8000	# r4 <- 1000 0000
		nand	3, 3, 4		# r3 <- (a - b) NAND 10000000
		addi	4, 0, -1	# r4 <- 1111 1111
		bne	3, 4, aLTb	# if (a - b) < 0 skip to aLTb

	aGTb:	sw	2, 0, a		# a = -b
		jump	 next		# goto next

	aLTb:	nand	1, 1, 1		# r1 <- a NAND a (flips bits)
		addi	1, 1, 1		# r1 <- -a
		sw	1, 0, b		# b = -a

	next:	...

	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	this example show the value of subroutines
	and the use of the JALR instruction

	if (a == 0) {
	    a += (b * 4) - 1;
	    b++;
	} else if (a < 0) {
	    a += (c * 4) - 1;
	    c++;
	} else {		/* if a > 0 */
	    a += (d * 4) - 1;
	    d++;
	}

	what we're going to do here is create a
	subroutine that takes as input a value
	in register 5.  the subroutine multiplies
	this number by 4, then subtracts 1 from
	the product, then adds the value of a (in
	register 1), and stores the result to a.

	the subroutine also increments the value in
	register 5.  when we return from the 
	subroutine, we store this value to memory.

	note that JALR jumps through a register and
	there is no simple way to get an ADDRESS into
	a register (you cannot, for example, use lw
	directly on the label).  so we have to create
	an intermediate label called jAddr that holds
	the address of subr.

		lw	1, 0, a		# r1 <- a
		lw	2, 0, jAddr	# r2 <- addr of subr
		bne	1, 0, aNEz	# if (a == 0) skip to aEQz

	aEQz:	lw	5, 0, d		# r5 <- d
		jalr	2, 7		# jump to subr, link in r7
		sw	5, 0, d		# d++;
		jump	next		# skip to next

	aNEz:	lui	3, 0x8000	# r3 <- 1000 0000
		nand	4, 1, 3		# r4 <- a NAND 10000000
		addi	3, 0, -1	# r3 <- 1111 1111
		bne	4, 3, aLTz	# if (a < 0) skip to aLTz

	aGTz:	lw	5, 0, c		# r5 <- c
		jalr	2, 7		# jump to subr, link in r7
		sw	5, 0, c		# c++;
		jump	next		# skip to next

	aLTz:	lw	5, 0, b		# r5 <- b
		jalr	2, 7		# jump to subr, link in r7
		sw	5, 0, b		# b++;
		jump	next		# skip to next

	subr:	add	6, 5, 5		# r6 = r5 * 2
		add	6, 6, 6		# r6 *= 2 (now r6 = r5 * 4)
		addi	6, 6, -1	# r6 = r6 - 1
		add	1, 1, 6		# a += ( x * 4 ) - 1
		sw	1, 0, a		# store a
		addi	5, 5, 1		# r5++
		jalr	7, 0		# return from subroutine

	next:	...
	jAddr:	.fill	subr