CSCI206 - Computer Organization & Programming Procedures and Recursions zyBook: 8.2
Two’s complement multiplication When doing two’s complement multiplication, the signs will take care of themselves. The values (operands) must be fully “sign-extended” before operation (multiplication)! The result of two n-bits values will have 2*n bits. Thus sign extension must be 2*n bit long. We will discuss the topic in greater detail in Chapter 10
Examples Discussions and examples are from (2/23/2017) http://pages.cs.wisc.edu/~smoler/cs354/beyond354/int.mult.html A 4-bit, 2’s complement example: (-1) * (-7) == 7, extending to 8 bits 1111 1111 (-1) X) 1111 1001 (-7) ------------------------------------ 11111111 00000000 +) 11111111 ----------------------------------- 1111100000000111 ---> 7 Computer will extend the sign automatically to the full bits 1111100000000111 becomes 0000000000000111
Examples A 4-bit 2’s complement example 3*(-5) == -15, extending to 8 bits 0000 0011 (3) X) 1111 1011 (-5) ---------------------- 00000011 00000000 +) 00000011 0000001011110001 ---> -15 Computer will extend the sign automatically to the full bits 0000001011110001 becomes 1111111111110001 Run the program mult.s in MARS
Factorial int fact (int n) { if (n < 1) return (1); else return (n * fact(n-1)); } To implement factorial, we need to use the mult instruction in MIPS.
Factorial (1) Stack $ra One call to fact $a0 $sp fact: # PC == 0x0040001c addi $sp, $sp, -8 # create space for 2 items sw $ra, 4($sp) # save return address sw $a0, 0($sp) # save argument slti $t0, $a0, 1 # $t0 = 1 if n < 1 beq $t0, $zero, Else # if n>=1, go to Else addi $v0, $zero, 1 # return 1 addi $sp, $sp, 8 # pop 2 words off the stack jr $ra # return to caller Else: # PC == 0x0040003c addi $a0, $a0, -1 # n>=1: n = n-1 jal fact # fact(n=n-1) PC == 0x00400040 lw $a0, 0($sp) # restore save argument n lw $ra, 4($sp) # restore return address mul $v0, $a0, $v0 # $v0 = n * fact(n-1) int fact (int n) { if (n < 1) return (1); else return (n * fact(n-1)); }
Factorial (2) local / automatic variable, located on the stack 1 2 3 4 5 6 7 8 9 10 11 int fact (int n) { int result; if (n < 1) result = 1; else result = n * fact(n-1); return result; } local / automatic variable, located on the stack single return, value from stack
Factorial (2) fact: addi $sp, $sp, -12 # create space for 3 items sw $ra, 8($sp) # save return address sw $a0, 4($sp) # save argument slti $t0, $a0, 1 # $t0 = 1 if n < 1 beq $t0, $zero, Else # if n>=1, go to Else li $t0, 1 # setup for base-case sw $t0, 0($sp) # store 1 in result j fact_return Else: addi $a0, $a0, -1 # n>=1: n = n-1 jal fact # fact(n=n-1) PC = 0x0x01FC lw $a0, 4($sp) # restore saved argument n mul $t0, $a0, $v0 # $v0 = n * fact(n-1) sw $t0, 0($sp) # store result on stack #fall through to return fact_return: lw $ra, 8($sp) # restore return address lw $v0, 0($sp) # get result addi $sp, $sp, 12 # pop 3 words off the stack jr $ra # return to caller Factorial (2) 1 2 3 4 5 6 7 8 9 10 11 int fact (int n) { int result; if (n < 1) result = 1; else result = n * fact(n-1); return result; }
fact: addi $sp, $sp, -8 # create space for 3 items sw $ra, 4($sp) # save return address sw $a0, 0($sp) # save argument slti $t0, $a0, 1 # $t0 = 1 if n < 1 beq $t0, $zero, Else # if n>=1, go to Else li $v0, 1 # setup for base-case j fact_return Else: addi $a0, $a0, -1 # n>=1: n = n-1 jal fact # fact(n=n-1) lw $a0, 0($sp) # restore saved argument n mul $v0, $a0, $v0 # $v0 = n * fact(n-1) #fall through to return fact_return: lw $ra, 4($sp) # restore return address addi $sp, $sp, 8 # pop 2 words off the stack jr $ra # return to caller Factorial (2b) 1 2 3 4 5 6 7 8 9 10 11 int fact (int n) { int result; if (n < 1) result = 1; else result = n * fact(n-1); return result; } Because result is assigned after all other function calls, we can use a register to hold this local variable. This is an optimization!
Factorial (3) Delayed stack setup is ok! blt $a0, 13, check_facts # check n li $v0, 0 jr $ra # if n > 12, return immediately check_facts: sll $t0, $a0, 2 # byte offset of n lw $v0, facts($t0)# load facts[n] bgtz $v0, fact_return # branch if lookup worked compute_fact: slti $t0, $a0, 1 # $t0 = 1 if n < 1 beq $t0, $zero, L1 # if n>=1, go to L1 li $v0, 1 # setup for base-case j fact_return L1: addi $sp, $sp, -8 # create space for 2 items sw $ra, 4($sp) # save return address sw $a0, 0($sp) # save argument addi $a0, $a0, -1 # n>=1: n = n-1 jal fact # fact(n=n-1) PC = 0x0x01FC lw $a0, 0($sp) # restore saved argument n lw $ra, 4($sp) # restore return address mul $v0, $a0, $v0 # $v0 = n * fact(n-1) addi $sp, $sp, 8 # pop 2 words off the stack #fall through to return fact_return: sll $t0, $a0, 2 # byte offset sw $v0, facts($t0)# save result in facts[n] jr $ra # return to caller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int facts[12] = {0}; int fact (int n) { if (n > 12){ return 0; } if (facts[n] == 0){ if (n < 1){ facts[n] = 1; } else { facts[n] = n * fact(n-1); return facts[n]; Delayed stack setup is ok! Use look-up table for previously computed results!