Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Instruction Set Architecture Classification According to the type of internal storage in a processor the basic types are • Stack • Accumulator • General Purpose register • Register – Memory • Register – Register/ Load – Store • Memory – Memory (obsolete) • Extended accumulator/extended general purpose register Processor Stack • A Top-of-Stack (TOS) register points to the top input operand, which is combined with the operand below • The first operand is removed from the stack, and the result is stored in the place of the second operand, while TOS is updated TOS ... ALU Memory ... ... Accumulator One operand implicitly in accumulator, the other in memory and result in accumulator ALU ... ... ... Register - Memory One operand is in a register the other in memory and the result is stored in a register ... ALU ... ... ... Register – Register/ Load – Store ... Both operands and result are stored in registers ALU ... ... Addressing Modes • • • • • • • • • • Register • ADD R4, R3 ; Regs[R4] ←Regs[R4] + Regs[R3] Immediate • ADD R4, #3 ; Regs[R4] ←Regs[R4] + 3 Displacement • ADD R4, 100(R1) ; Regs[R4] ←Regs[R4] + Mem[100+Regs[R1]] Register Indirect • ADD R4, (R1) ; Regs[R4] ←Regs[R4] + Mem[Regs[R1]] Indexed • ADD R3, (R1+R2) ; Regs[R3] ←Regs[R3] + Mem[Regs[R1]+ Regs[R2]] Direct or absolute • ADD R1, (1001) ; Regs[R1] ←Regs[R1] + Mem[1001] Memory indirect • ADD R1, @(R3) ; Regs[R1] ←Regs[R1] + Mem[Mem[Regs[R3]]] Autoincrement • ADD R1, (R2)+ ; Regs[R1] ←Regs[R1] + Mem[Regs[R2]] Regs[R2] ← Regs[R2] + d Autodecrement • ADD R1, -(R2) ; Regs[R2] ← Regs[R2] - d Regs[R1] ←Regs[R1] + Mem[Regs[R2]] Scaled • ADD R1, 100(R2)[R3] ; Regs[R1] ←Regs[R1] + Mem[100 + Regs[R2] + Regs[R3]*d] Instruction encoding • Variable length (x86) • Fixed length (ARM, MIPS, PowerPC) • Hybrid (MIPS16, Thumb, TI TMS320C54x) Taking orders • A computer does what you tell it to do • Not necessarily what you want it to do... • We give computers orders by means of instructions • Instructions tell the computer what it should be doing, right now • Arithmetic • Logic • Data movement • Control 3.1 Binary review Binary representations of numbers consist of only 1’s and 0’s 01012 = 510 10002 = 810 11111112 = 12710 Unsigned (always positive) binary numbers Binary Facts: 210 = 1024 = 1K 1,000 220 = 1,048,576 = 1M 1,000,000 230 = 1,073,741,824 = 1G 1,000,000,000 Converting between binary and hex Binary 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 Hexadecimal 0 1 2 3 4 5 6 7 8 9 A B C D E F Group bits together in groups of 4 10001100101100100001112 --> 10 0011 0010 1100 1000 01112 Assign the appropriate hex digit to each group 10 0011 0010 1100 1000 01112 --> 2 3 2 C 8 7 Done = 232C8716 The Translation Process Computers speak in binary. We don’t. High-level language A=B+C Assembly language Compiler add $1, $2, $3 Compilers and Assemblers translate from one language to another. Assembler Machine language 000000 00010 00011 00001 00000 100000 3.2 MIPS Instructions Operation add Destination A, B, Sources C A=B+C sub D, A, D =A-B B In MIPS, All register-to-register arithmetic instructions have three operands. 3.2 Operands add A, B, C What are A, B, and C? The operands of arithmetic instructions are always registers add $17, $18, $19 Add contents of registers 18 and 19 and put result in register 17 sub $19, $19, $18 Subtract $19 - $18 and put the result back in $19 3.3 Registering 47 $2 • MIPS has 32 general-purpose registers • $0 through $31 • Each register holds 32 bits • 0 to 232 -1 (4 billion) if unsigned • -231 to +231-1 (-2 billion to +2 billion) if signed • Most registers can hold any value, for any purpose • Exception: $0 is always zero! 3.3 Register Naming and Conventions • In MIPS, all registers (except $0) can be used for any purpose desired • However, there are standard use conventions that make it easier to write software # $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 Name $zero $at $v0 $v1 $a0 $a1 $a2 $a3 $t0 $t1 $t2 $t3 $t4 $t5 $t6 $t7 Purpose Constant zero Reserved for assembler Function return value Function parameter Temporary – Caller-saved # $16 $17 $18 $19 $20 $21 $22 $23 $24 $25 $26 $27 $28 $29 $30 $31 Name $s0 $s1 $s2 $s3 $s4 $s5 $s6 $s7 $t8 $t9 $k0 $k1 $gp $sp $fp $ra Purpose Temporary – Callee-saved Temporary – Caller-saved Reserved for OS Global pointer Stack pointer Frame pointer Function return address Reflections on Registers • Registers are just “special” memory locations • A small number of registers, as opposed to a huge number of memory locations • Because there are a small number of registers, accessing them is fast • Principle: Smaller is usually faster. • Trade-offs • More registers --> More data in fast memory --> Faster execution • Fewer registers --> Registers are faster --> Faster execution • Compromise: 16 to 32 registers works well 3.3 Complicated arithmetic F = (A + B) - (C + D) Assume: A is in $8 B is in $9 C is in $10 D is in $11 F is in $12 add add sub $12 = ($8 + $9) - ($10 + $11) Note: Typically, the compiler assigns variables to registers $13, $8, $9 $14, $10, $11 $12, $13, $14 We don’t have a 5-operand add/subtract instruction! Use temporary variables to solve the problem. # $13 <-- A + B # $14 <-- C + D # F <-- (A+B) - (C+D) $13 and $14 are temporary variables 3.3 Getting to the bits of it all We’ve looked at assembly language (briefly) The CPU wants bits. R-Type Instruction add $13, $8, $9 Assembler 000000 01000 01001 01101 00000 100000 0 Opcode 32 bits, total 8 9 RS RT 13 0 32 RD ShAmt Function 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits 0 = Add $8 $9 $13 0 32=Add 3.4 Staying Regular R-Type instructions all have the same format: Opcode 6 bits RS 5 bits RT 5 bits RD ShAmt Function 5 bits 5 bits 6 bits Add has an opcode of ‘0’, a function of ‘32’ add $13,$8,$9: 000000 01000 01001 01101 00000 100000 Subtract has an opcode of ‘0’, a function of ‘34’ sub $13,$8,$9: 000000 01000 01001 01101 00000 100010 The instructions differ only in one bit! Regularity: Similar functions should be similar in format. Regularity is a key to high-performance 3.4 Constants Many times, an instruction needs to use a constant value • Multiply by 4 • Add 3 Instructions with constant data in them are called immediate instructions • addi $12, $10, 4 # Reg. 12 <-- Reg. 10 + 4 add immediate I-Type instructions all have the same format: Opcode RS RT 6 bits 5 bits 5 bits 8 10 12 001000 01010 01100 I-Type Instruction Immediate Data 16 bits 4 0000 0000 0000 0100 3.8 Doing Double Duty • You desire to copy the value in register $8 to $10 • Called a “move” in computer terms • move $10, $8 #copy register $8 to $10 • Doesn’t exist in MIPS assembly language! • add $10, $8, $0 # adds zero and $8, result in $10 • Does the same thing as a move • Allows the add instruction to serve double duty! • Many instructions have double/triple functions • sub $8, $0, $8 # negate $8 • addi $12, $0, 4 # load register $12 with value 4 3.4 Thanks for all the Memory! When 32 registers just won’t do. Many times (almost all the time, actually), you can’t fit all of your data into 32 registers. What do you do? Put some (most) of the data in main memory. Remember: Smaller is faster. Registers: Small and Fast Memory: Big and Slow In MIPS, all operations (i.e. arithmetic) are done on registers, only. Memory is used only for storing what won’t fit in registers. 3.3 Loading and Storing So you’ve got some data in memory. Big deal. You need it in a register to do anything useful. 3288 44 43 234 0996 1000 1004 You need to load a register with a value from memory. lw $10, 1000($0) # copy memory location 1000 to $10 Afterwards, $10 has the value 43 Load Word Loads a whole 32-bit word This value is added to 1000 - for now, it is zero Say you’ve added 1 to register $10 (now it has the value 44). Now you want to put it back in memory again. You need to store the register’s value back to memory. sw $10, 1000($0) # copy $10 to memory location 1000 3.3 Aside: Load and Store Architectures • The only way to communicate with memory is through a LW or SW instruction • If you want to operate on memory, you have to use at least three instructions (usually) lw $15, 4500($0) add $15, $15, $3 sw $15, 4500($0) # load M[4500] into $15 # add $3 to $15 # store $15 back into M[4500] • It doesn’t have to be this way • Contrast this with the Motorola 68000 • ADD D3, 4500 ; add register D3 to M[4500] • Is the grass greener on the other side? • MIPS: Takes more, simpler instructions... RISC • MC68000: Takes fewer, complex instructions... CISC 3.3 Data Structures - Arrays A single-dimensional array (vector) is a simple linear data structure int A[5]; /* integers are 4 bytes each */ 2000 2004 2008 2012 2016 2020 2024 2028 A[0] A[1] A[2] A[3] A[4] start of array (2004 in this example) For 4-byte integers: Location of A[n] = Start + n*4; For data items of size s bytes: Location of A[n] = Start + n*s; Accessing data in memory Assume that the variable List points to the beginning of an array of 32-bit integers. ... List=6000 6000 123 List[0] 3288 List[1] 6004 Move List[0] into $3: 43 List[2] 6008 lw $3, List($0) # $3 <-- List[0] 1 List[3] 6012 6016 45 List[4] Move List[1] into $4: ... addi $8, $0, 4 # $8 <-- 4 Note: Memory addresses lw $4, List($8) # $4 <-- List[1] refer to 8-bit bytes! We List and contents of $8 are added together to form address Move List[4] into $5: addi $8, $0, 16 # $8 <-- 16 lw $5, List($8) # $5 <-- List[4] usually reference 32-bit words. All lw/sw instructions must use an address that is a multiple of 4! To get proper index, have to multiply by 4. 3.3 Load/Store Format • What instruction format do LW and SW have? • lw $5, 240($9) # load M[240+$9] into $5 • Needs • Opcode • Source register ($9) • Immediate Operand (240) • Destination register ($5) • Hmmm, we’ve seen this before.... Opcode for LW: 35 Opcode 6 bits Opcode for SW: 43 35 RS 5 bits 9 RT 5 bits 5 100011 01001 00101 I-Type Instruction Immediate Data 16 bits 240 0000 0000 1111 0000 Think Regularity! 3.4 Assembler directives • Somehow, we’ve got to get data into memory • User input • Involves system calls (we’ll get to that later) • Constant data • Constant data is data that is in memory before our program starts executing • Machine-language instructions don’t give much help • The only way is to use Immediate instructions • The assembler helps us here! • Assembler directives are special commands to the assembler. The most common directives put data into memory. A.10 .word Assembler Directive Buffer: .word Label: A name for this memory to go by. Acts as a variable name. Buffer: Buffer+ 4: 01, 02 Data to be stored. .word: Directive to store words in memory here. Remember: 00 00 00 01 Words are 4 bytes each! 00 00 00 02 Loads from Buffer+0 Loads from Buffer+4 lw $12, Buffer($0) addi $10, $0, 4 lw $13, Buffer($10) # $12 <-- 00 00 00 01 # $10 <-- 4 # $13 <-- 00 00 00 02 A.10 The Assembler Location Counter The assembler keeps track of where to put things by using a location counter. The location counter just points to the memory location to put the “next” item. For this example, assume the location counter starts at 4000 Loc. Ctr. 4004 4008 Label Table buffer1: .word 12 4000: 4004: buffer2: .word 3, 4, 0x20, 0x5 buffer1 = 4000 buffer2 = 4004 firstld = 4024 secld = 4032 4020: 4024: firstld: 4028: 4032: secld: add lw addi lw Hex Constants a denoted by the “0x” prefix 4012 $9, $0, $0 $8, buffer1($9) $9, $9, 4 $10, buffer2($9) 4016 Data Structures? No, thanks • Assembly has no concept of “data structures” • You can access a “variable” using another “variable” .data Tonto: .word Tonto2: .word 0x44, 0x22 0x32 .text main: add lw addi lw addi lw addi syscall $9, $0, $0 $8, Tonto($9) $9, $9, 4 $10, Tonto($9) $9, $9, 4 $10, Tonto($9) $v0,$0,10 # clear $9 # put Tonto[0] in $8 # increment $9 # put Tonto[1] in $10 # increment $9 # put Tonto[2] ???? in $10 Other Memory Assembler Directives borg: .byte borg: 10 ? greeting: greeting: greeting2: greeting2: .byte - reserves bytes in memory 33, 22, 12, 10, 8, 1 12 ? 22 1 33 8 .asciiz “Resistance is small.” 52 65 73 69 6C 65 2E 0 .ascii ... “You will be informed.” 59 6F 75 65 64 2E ... .asciiz - reserves Nullterminated ASCII chars Null-terminated .ascii - reserves ASCII characters (no NULL) 20 -- A.10 Meeting all your needs for space Sometimes, we need to allocate (empty) space to be used later. inputbuffer: .space 100 Allocates 100 bytes of space for an input buffer. Space allocated this way is just reserved by the assembler. You have to make your own use of it. addi sw $12, $0, 6 $12, inputbuffer($0) # stores 6 in buffer A.10 Our first program! # This is our first program! Yeah! .data Tonto: .word .text .data means that data follows 0x44, 0x22 .text means that code follows main: tells SPIM where to start main: add lw addi lw $9, $0, $0 $8, Tonto($9) $9, $9, 4 $10, Tonto($9) addi $v0,$0,10 syscall # clear $9 # put Tonto[0] in $8 # increment $9 # put Tonto[1] in $10 these two instructions end the program A.10 Instruction 1 add $6, $0, $0 2 add $7, $0, $0 3 lw $5, ARRAY($7) 4 add $6, $6, $5 5 addi $7, $7, 4 6 lw $5, ARRAY($7) 7 add $6, $6, $5 8 addi $7, $7, 4 9 lw $5, ARRAY($7) 10 add $6, $6, $5 11 addi $7, $7, 4 12 lw $5, ARRAY($7) 13 add $6, $6, $5 14 addi $7, $7, 4 15 lw $5, ARRAY($7) 16 add $6, $6, $5 17 sw $6, SUM($0) 18 addi $v0, $0, 10 PC R5 R6 R7 Logic Instructions • and $10, $8, $6 # bitwise and between $8 and $6, result in $10 • Example: • • • • • • • • $8 = 0010 0001 1100 0001 0011 1100 1010 0000 • $6 = 1101 1110 0011 0001 1111 0000 1100 0001 • $10=0000 0000 0000 0001 0011 0000 1000 0000 or $10, $8, $6 # bitwise or between $8 and $6, result in $10 xor $10, $8, $6 bitwise xor between $8 and $6, result in $10 The above are R-Type instructions andi $10, $8, 6 # bitwise and between $8 and 6, result in $10 • Example: • $8 = 0010 0001 1100 0001 0011 1100 1010 0000 • 6 = 0000 0000 0000 0000 0000 0000 0000 0110 • $10=0000 0000 0000 0000 0000 0000 0000 0000 ori $10, $8, 6 # bitwise or between $8 and 6, result in $10 xori $10, $8, 6 bitwise xor between $8 and 6, result in $10 The above are I-Type instructions Example • Write at least 5 ways of clearing a register • Write at least 4 ways of copying the contents of a register to another register Pseudoinstructions • Some “missing” instructions are commonly composed of others • The assembler “implements” these by allowing the “missing” instructions to be entered in assembly code. • When machine code is generated, the pseudoinstructions are converted to real instructions. • Pseudoinstructions are assembler-dependent • They can be turned-off in SPIM move $5, $3 add $5, $3, $0 neg $8, $9 sub $8, $0, $9 li $8, 44 addi $8, $0, 44 or ori $8, $0, 44 A.10 SPIM I/O • SPIM I/O uses the SYSCALL pseudoinstruction • Set up parameters • Place correct code in $v0 • Execute SYSCALL Action Print an Integer Print a String Input an Integer Input a String Exit program Code (in $v0) 1 4 5 8 10 To print the value in $t3: move $a0, $t3 li $v0, 1 syscall Parameters $a0 = value to print $a0 = location of string (after syscall) $v0 contains integer $a0 = location of buffer, $a1 = length To display a string prompt: .asciiz “hello world” la $a0,prompt li $v0, 4 syscall Boring • Straight-line code is nice, but boring • Just arithmetic and loads/stores based on a predetermined sequence • Decision-making elements add some spice to the equation • Control allows programs to make decisions based on their current state • The most common control structure is the branch A = B+C D = B+F M[18]=D D = B+F D>23? Y N M[22] = D C = B+A 3.5 Going places Consider the GoTo if (x == y) q = 13; Next: if (x != y) GoTo Next; q = 13; ... if (p > q) r = 3; else r=2; while (y < 2) y = y+1; Loop: End: if (y >=2) GoTo End; y = y+1; GoTo Loop; ... R3: Next: if (p>q) GoTo R3; r = 2; GoTo Next; r = 3; ... if (condition) GoTo location and GoTo location are all we need 3.5 Branching out if ($9 == $10) GoTo Label; beq $9, $10, Label if ($7 != $13) GoTo Next; bne beq - Branch if EQual bne - Branch if Not Equal $7, $13, Next Branches use I-Type Instruction Format (need two registers and 16-bit data) GoTo Exit; j Exit j - Jump (unconditionally) Jumps need only an opcode and data There is a lot more room for the data... Opcode 6 bits Immediate Data 26 bits J-Type Instruction 3.5 IF-Then Structures if $x == $y then S1 S2 S1 should be executed if $x == $y is True If $x != $y, or after S1 is executed, S2 is executed False: bne S1 S2 $x, $y, False # if $x != $y, skip S1 # $x == $y, execute S1 # either way we get here, execute S2 If you can’t express the condition as a negative, try this: True: False: beq j S1 S2 $x, $y, True False # if $x == $y, then execute S1 # $x != $y, so exit # $x == $y, execute S1 # either way we get here, execute S2 3.5 IF-Then-Else Structures if $x == $y then S1 else S2 S3 S1 should be executed if $x == $y S2 should be executed if $x != $y After executing S1 or S2, execute S3 IF: Finish: beq S2 j S1 S3 $x, $y, IF Finish # if $x == $y, goto S1, skip S2 # $x != $y, execute S2 # now execute S3 # $x == $y, so execute S1 # either way, we do S3 afterwards 3.5 More Complicated If-Then-Else structures if $x == $y and $z == $w then S1 else S2 S3 S1 should be executed if both $x == $y and $z == $w S2 should be executed if either $x != $y or $z != $w After executing S1 or S2, execute S3 The simplest way to figure out complex if-then-else structures is to first write the conditions, then all the statements and finally figure out the branches and jumps STEP 1: conditions STEP 2: statements STEP 3: branches bne $x, $y, ____ bne $x, $y, ____ bne $x, $y, false bne $z, $w, false bne $z, $w, ____ bne $z, $w, ____ S1 j skip S1 false: S2 S2 skip: S3 S3 Example if $x == $y or $z == $w then S1 else if $x == $z or $y == $w then S2 else S3 STEP 1: conditions bne $x, $y, ____ beq STEP 2: statements beq $x, $y, ____ bne $z, $w, ____ beq beq $z, $w, ____ beq $x, $z, ____ beq $x, $z, ____ beq $y, $w, ____ beq $y, $w, ____ STEP 3: branches beq $x, $y, then1 beq $z, $w, then1 beq $x, $z, then2 beq $y, $w, then2 j skip then1: S1 j skip then2: S2 S1 S2 S3 skip: S3 Interlude: Comments on Comments • Code should be thoroughly commented • Code may be modified by different programmers • Code may be reused a long time after writing it • There are two types of commenting style depending on the reader of the code the comments are intended for • Comments that explain what the instruction does • Typical for programming language books and lecture notes • The purpose is to learn the language • Worthless if used in a real program • Comments that explain the logic behind the instruction • Typical for real programs, assumes reader knows language • The purpose is to understand the program • Not helpful for learning the language • Examples: • addi $7, $7, 4 #add 4 to R7, R7<-R7+4 #incrementing address • lw $5, ARRAY($7) #R5 <- [ARRAY+4] #fetching next ARRAY #element While Loops while $x == $y do S1 Execute S1 repeatedly as long as $x == $y is true Repeat: bne S1 j Exit: $x,$y, Exit Repeat # exit if $x != $y is False # execute body of loop # do it all over again # end of the loop Warning: The following loop always executes at least once, no matter what $x and $y are: Repeat: S1 beq Exit: $x,$y, Repeat # execute body of loop # do it again if $x == $y # end of the loop 3.5 For Loops for i = $start to $finish {S1} S2 Use temporary, $t0 to hold i Execute S1 for all values from $start to $finish (step of 1) move Loop: bgt S1 addi j done: S2 $t0, $start # copy start to i ($t0) $t0, $finish, done # if i > finish, then we’re done - do S2 # execute S1 $t0, $t0, 1 # increment count Loop # go again Note: bgt doesn’t really exist - more on that later... 3.5 Other conditions slt $4, $10, $11 Set on Less Than Set $4 = 1 if ($10 < $11), otherwise $4 = 0 if ($7 < $8) then $15 = 3; slt beq addi $1, $7, $8 $1, $0, GoOn $15, $0, 3 Example: $7=4, $8=9 $1 = 1 ( $7 < $8) $1 0, Don’t branch Set $15 to 3 Example: $7=4, $8=2 $1 = 0 ( $7 > $8) $1 == 0, Branch GoOn ($15 not changed) # $1 <-- ($7 < $8) # If not less than, go on # ($7 < $8), so $15 <-- 3 GoOn: if ($12 >= $3) then $4 = $2; slt bne add $1, $12, $3 $1, $0, GoOn $4, $2, $0 Example: $12=4, $3=2 $1 = 0 ( $12 > $3) # $1 <-- ($12 < $3) $1 == 0, Don’t branch # If less than, go on # ($12 >= $13), so $4 = $2 Set $4 to 2 GoOn: 3.5 Pseudoinstructions for branches • Branches can be nasty to figure out • SPIM provides several pseudoinstructions for branches blt $3, $4, dest slt bne $1, $3, $4 $1, $0, dest bge $3, $4, dest slt beq $1, $3, $4 $1, $0, dest $3 >= $4 is the opposite of $3 < $4 bgt $3, $4, dest slt bne $1, $4, $3 $1, $0, dest $3 > $4 same as $4 < $3 ble $3, $4, dest slt beq $1, $4, $3 $1, $0, dest $3 <= $4 is the opposite of $3 > $4 A.10 Branch limitations • A conditional branch (BEQ, BNE) uses an I-type Instruction • Allows a 16-bit immediate operand • 216 = 64K Locations is too small • Notice that most branches don’t go very far away (back to the beginning of a loop, etc.) • Use PC-relative addresses for branches • Immediate operand is a displacement in 4-byte words from the next instruction • May be positive (forward branches) or negative (backwards branches) 3.8 Branch example loop: bgt lw addi beq bigger: move Branches: offset is in instructions from the instruction following the branch 8000 8004 8008 8012 8016 8020 $t0, $t1, bigger $s0, 0($t0) $t0, $t0, 1 $s0, $s1, loop $s2, $t0 loop: -5 instructions loop: slt $1, $8, $9 +3 bne $1, $0, bigger lw $16, 0($8) addi $8, $8, 1 -5 beq $16, $17, loop bigger: add $18, $8, $0 bigger: + 3 instructions 8000 8004 8008 8012 8016 8020 0 5 35 8 4 0 8 1 8 8 16 8 9 0 16 8 17 0 1 18 0 +3 0 1 -5 0 42 32 Note: Negative numbers require 2’s complement 3.8 Jump Addressing • Jumps use a J-type instruction and have a 26-bit offset • A lot more range than 16-bit branches • Allows a range of 226=64M possibilites • Because the range is so much larger, jumps use absolute addressing • Absolute addressing just specifies the address of the jump target • Since all instructions have addresses that are multiples of 4, we only need to put the address divided by 4 in the instruction field • Actual byte address is obtained by multiplying by 4 • Allows a range of 64M instructions = 256M bytes Example: 2000 2004 2000: 2004: target: 2 0 2 j add 4 target 501 = 2004/4 $1, $2, $4 501 1 0 32 3.8 Jumping based on Registers • Jumps change the PC to a fixed location • j OverThere • Always goes to the same place • Is there a way to jump to a place to be determined by the program? • Put the address to go to in a register • addi $14, $0, 10000 • Jump to the address contained in that register • jr $14 JR - Jump Register 3.5 LUI • Registers can hold 32 bits, but we can only load in 16-bit immediate data • LUI - Load Upper Immediate • Loads constant into bits 31-16 of register • Bits 15-0 become zero Put the constant 0x1A2B3C4D in register $8 lui li $8, 0x1A2B $8, 0x3C4D Warning: Don’t use addi for the second instruction; use LI or ORI. (Sign Extension) ---- 1A2B $8: 31 We can let the assembler do the work: li $8, 0x1A2B3C4D will be converted to these two instructions ---- 0000 3C4D 16 15 0 3.8 Getting around branch limitations Branches have a limit of +/- 215 instructions - How can we branch further? 1000: beq $s0,$t1,far 1004: sub $s2, $v0, $a0 … 500000: far: add $t1, $t2, $t3 Can’t branch that far... 1000: bne 1004: j 1008: stay: sub … 500000: far: add $s0,$t1,stay far $s2, $v0, $a0 $t1, $t2, $t3 Use the larger range of the jump instruction: 3.8 Example Instruction R5 R6 R7 Addr:Data 1 add $6, $0, $0 8000: 0x3 2 addi $7, $0, 8 8004: 0x4 3 lw $5, ARRAY($7) 8008: 0x5 4 add $6, $6, $5 800C 5 addi $5, $0, 0 8010 6 lui $5, 0x5 8014 7 be $5, $0, EXIT 8018 8 slt $5, $0, $6 801C 9 li $7, 0x8000 8020 10 lw $5, 0($7) 11 and $5, $5, $7 12 bgt $5, $6, EXIT 13 li $7, 0xC 14 sw $5, 8000($0) 15 sw $6, 8000($4) 16 j EXIT 17 sw $7, 8014($0) 18 EXIT: The Stack • • • • • • • • A stack is a one-dimensional data structure The stack segment of a program is used for temporary storage of data and addresses Items are added to and removed from one end of the structure using a "Last In - First Out" technique (LIFO) The top of the stack is the last addition to the stack Every program has three segments of memory assigned to it by the operating system • the “text” segment where the machine language code is stored, • the “data” segment where space is allocated for global constants and variables, • the stack segment. The stack segment is provided as an area where • parameters can be passed, • local variables for functions are allocated space, • return addresses for nested function calls and recursive functions are stored The operating system initializes register 29 ($sp) in the register file to the base address of the stack area in memory The stack grows toward lower addresses The Stack • MIPS has no special push and pop instructions • However the following instructions are equivalent • PUSH addi $sp, $sp, -4 sw $5, 0($sp) #decrement stack pointer #save $5 to stack • POP lw $5, 0($sp) #load from stack to $5 addi $sp, $sp, 4 #increment stack pointer Subroutines • Subroutines allow common program portions to be reused • int CalcInterest(int principle, int time) { ... } • y = CalcInterest(1000, 10) • z = CalcInterest(1000, 15) • When calling a subroutine, you must: • Set up any parameters • Save the current position so the program will know where to return to • Jump to the location of the subroutine 3.6 Jumpin’ and Linkin’ • JAL - Jump and Link • Saves the return address • Write address of next instruction in $31 ($ra) • Jumps to the address specified and keeps going 100: 104: 342: 346: 368: jal sub ... CALC: add mult ... jr CALC $4, $4, $2 $14,$15,$2 $14, $2 $ra Call the Calc subroutine Save addr. of next instr. in $ra ($31) 104 $ra Start of Subroutine End of Subroutine. Return to Return Address in $ra 3.6 Instruction R5 R6 R7 Addr:Data 1 add $6, $0, $0 8000: 0x3 2 addi $7, $0, 8 8004: 0x4 3 lw $5, ARRAY($7) 8008: 0x5 4 add $6, $6, $5 800C 5 addi $5, $0, 0 8010 6 jl CALC 8014 7 be $5, $0, EXIT 8018 8 slt $5, $0, $6 801C 9 li $7, 0x8000 8020 10 j EXIT 11 CALC: and $5, $5, $7 12 li $7, 0xC 13 sw $5, 8000($0) 14 sw $6, 8000($4) 15 sw $7, 8008($0) 16 jr $ra 17 sw $7, 8014($0) 18 EXIT: Passing Parameters • Most subroutines have parameters to make them more interesting... • Z = Addemup(A,B,C) • In order to pass parameters, we must place the parameters in registers before calling the subroutine • $a0, $a1, $a2, $a3 used for these ($4 - $7) • $a0 <-- A, $a1 <--B, $a2 <--C • Before calling a routine, copy all parameters to the appropriate registers • Return values are put in $v0, $v1 ($2, $3) • $v0 <-- Z • After subroutine finished, copy return values back 3.6 Thoughts about MIPS programming • Write the program in C/C++ first • Break it into procedures as appropriate • Convert the program to assembly language • Start out simple • Get basic parts working before adding error checking, etc. • Don’t forget: Words are 4 bytes • Use pseudoinstructions when applicable Example • Write a MIPS assembly program that finds the sum of 5 numbers found in consecutive memory locations starting at array and stores it in memory location sum. .data ARRAY: .word 3, 5, 7, 9, 2 #random values SUM: .word 0 #initialize sum to zero .text main: addi $6, $0, 0 #set loop counter to 0 addi $9, $0, 5 #cannot compare with 5 directly addi $7, $0, 0 #set pointer to zero addi $8, $0, 0 #set $8 (sum temp) to zero REPEAT: lw $5, ARRAY($7) add $8, $8, $5 addi $7, $7, 4 #increment pointer addi $6, $6, 1 #increment loop counter bne $6, $9, REPEAT sw $8, SUM($0) #copy sum to memory addi $v0, $0, 10 #exit program syscall Example (improved version) • We can improve the previous program if we consider that comparing with zero is free in MIPS, so we can count down to zero instead of up to five. This saves one instruction and one register .data ARRAY: .word 3, 5, 7, 9, 2 #random values SUM: .word 0 #initialize sum to zero .text main: addi $6, $0, 5 #initialize loop counter to 5 addi $7, $0, 0 #initialize array index to zero addi $8, $0, 0 #set $8 (sum temp) to zero REPEAT: lw $5, ARRAY($7) #R5 = ARRAY[i] add $8, $8, $5 #SUM+= ARRAY[I] addi $7, $7, 4 #increment index (i++) addi $6, $6, -1 #decrement loop counter bne $6, $0, REPEAT #check if 5 repetitions sw $8, SUM($0) #copy sum to memory addi $v0, $0, 10 #exit program syscall Example (improved v2) • We can eliminate the loop counter and use the index to the array as counter if we consider the end value 4*5=20.This saves one more instruction .data ARRAY: .word 3, 5, 7, 9, 2 #random values SUM: .word 0 #initialize sum to zero .text main: addi $6, $0, 20 #set loop counter to 20 addi $7, $0, 0 #set pointer to zero addi $8, $0, 0 #set $8 (sum temp) to zero REPEAT: lw $5, ARRAY($7) add $8, $8, $5 addi $7, $7, 4 #increment pointer bne $6, $7, REPEAT sw $8, SUM($0) #copy sum to memory addi $v0, $0, 10 #exit program syscall Example 2 • Modify the program to read five numbers from the keyboard and then move them to location ARRAY .data ARRAY: .space 20 #reserving space for 5 numbers SUM: .word 0 #initialize sum to zero PROMPT: .asciiz "Please enter five numbers" RESULT: .asciiz "The sum of the numbers you entered is:" .text main: addi $6, $0, 5 #set loop counter to 5 addi $7, $0, 0 #set pointer to zero addi $8, $0, 0 #set $8 (sum temp) to zero la $a0,PROMPT #print prompt li $v0, 4 syscall INPUT: li $v0, 5 syscall sw $v0, ARRAY($7) #moving input to array addi $7, $7, 4 #increment pointer addi $6, $6, -1 #decrement loop counter bne $6, $0, INPUT • Example 3 (1/3) Write a MIPS assembly program that finds the maximum of 5 positive numbers read from the keyboard, stores it to memory location max and prints the result on the screen. Use functions. main: .data ARRAY: .space 20 #20 bytes for the 5 numbers MAX: .word 0 #initialize sum to zero PROMPT: .asciiz "Please enter five numbers" RESULT: .asciiz "The maximum of the numbers you entered is:" .text la $a0,PROMPT #setup call to print prompt jal PRINT #call to print message jal READ #call to input function, reads from keyboard jal FINDMAX #call to findmax function la $a0,RESULT #setup call to print result jal PRINT move $a0, $8 #setup value to print jal OUTPUT #call to output function, prints to screen addi $v0, $0, 10 #exit program syscall Example 3 (2/3) PRINT: li $v0, 4 #print prompt syscall jr $ra READ: addi $6, $0, 5 #set loop counter to 5, setup input function addi $7, $0, 0 #initialize pointer REPEAT: li $v0, 5 syscall sw $v0, ARRAY($7) #moving input to array addi $7, $7, 4 #increment pointer addi $6, $6, -1 #decrement loop counter bne $6, $0, REPEAT jr $ra Example 3(3/3) FINDMAX: REPEAT: SKIP: OUTPUT: addi $6, $0, 5 #set loop counter to 5 addi $7, $0, 0 #set pointer to zero addi $8,$0, 0 #initial maximum lw $5, ARRAY($7) bge $8, $5, SKIP #if $8 > $5, keep current maximum move $8, $5 #else new maximum addi $7, $7, 4 #increment pointer addi $6, $6, -1 #decrement loop counter bne $6, $0, REPEAT sw $8, MAX($0) #copy MAX to memory jr $ra li $v0, 1 syscall jr $ra Example 4 Write a function to scan an array “X” of 10 bytes counting how many bytes are ASCII codes for: • a. upper case letters - U • b. lower case letters - L • c. decimal digits - D .data ARRAY: .asciiz “df12o@pZ4X” #data for test U: .word 0 #initialize sum to zero L: .word 0 D: .word 0 ASCII Table .text main: addi $5, $0, 10 addi $6, $0, 0 add $7, $0, $0 add $8, $0, $0 add $9, $0, $0 li $10, 48 li $11, 57 li $12, 65 li $13, 90 li $14, 97 li $15, 122 #set loop counter to 5 #set pointer to zero #U #L #D #0 #9 #A #Z #a #z REPEAT: lb $16, ARRAY($6) blt $16, $10, SKIP bgt $16, $11, LETTER addi $9, $9, 1 j SKIP LETTER: blt $16, $12, SKIP bgt $16, $13, LOWER addi $7, $7, 1 j SKIP LOWER: blt $16, $14, SKIP bgt $16, $15, SKIP addi $8, $8, 1 j SKIP SKIP: addi $6, $6, 1 bne $5, $6, REPEAT # if ASCII<’0’, neither #else if ASCII>’9’, not a number #else ‘0’<ASCII<‘9’, it’s a number #if 9<ASCII<‘A’, neither #else if ASCII>’Z’, not uppercase #else 9<ASCII<‘A’, uppercase # if ‘Z’<ASCII<’a’, neither #else if ASCII>’z’, neither #else ‘a’<ASCII<’z’, sw $7, U($0) sw $8, L($0) sw $9, D($0) addi $v0, $0, 10 syscall #exit program Saving registers and passing parameters through the stack • Subprograms are typically written by different programmers • Each programmer does not know which registers the others are using • Could overwrite each others data! • Don’t know where to find arguments and return results Example of overwriting data by mistake main: addi $t0, $0, 5 #main program needs 5 in $t0 jal FUNC1 add $t0,$t0, $t1 #now $t0 has wrong value FUNC1: addi $t0, $0, 10 #FUNC overwrites $t0 … jr $ra Solution: save data you need on the stack main: addi $t0, $0, 5 #main program needs 5 in $t0 addi $sp, $sp, -4 #decrement stack pointer sw $t0, 0($sp) #save $t0 to stack jal FUNC1 #before calling FUNC1 lw $t0, 0($sp) #load from stack to $t0 addi $sp, $sp, 4 #increment stack pointer add $t0,$t0, $t1 #now $t0 has correct value FUNC1: addi $t0, $0, 10 #FUNC can now use $t0 … jr $ra Passing parameters • Let’s create a function that adds two numbers • In high-level languages this would be x=SUM(a,b) • Where can a, b and x be found in assembly? main: jal SUM SUM: add $??, $??, $?? #SUM must know the registers … jr $ra Solution: Pass a, b and x through the stack main: addi $sp, $sp, -4 #decrement stack pointer sw $t0, 0($sp) #push a=$t0 to stack addi $sp, $sp, -4 #decrement stack pointer sw $t0, 0($sp) #push b=$t1 to stack jal SUM lw $t0, 0($sp) #load from stack to x=$t0 addi $sp, $sp, 4 #increment stack pointer SUM: lw $t0, 0($sp) #load from stack to $t0=a addi $sp, $sp, 4 #increment stack pointer lw $t1, 0($sp) #load from stack to $t1=b addi $sp, $sp, 4 #increment stack pointer add $t1, $t0, $t1 #no need to know the registers addi $sp, $sp, -4 sw $t1, 0($sp) jr $ra #decrement stack pointer #push x=$t1 to stack Example 5 • Write a program that loads a 20-byte string from memory stored in memory location MSG, converts lowercase letters to uppercase and vice versa, stores the modified string in memory location MSG2 and prints it on the screen. .data MSG: .asciiz “#8puIth45FaSdf12o@pZ” #data for test MSG2: .space 20 #reserve 20 bytes .text main: addi $5, $0, 20 #set loop counter to 20 addi $6, $0, 0 #set pointer to zero li $12, 65 #ASCII value of A li $13, 90 #ASCII value of Z li $14, 97 #ASCII value of a li $15, 122 #ASCII value of z loop: lb $16, MSG($6) blt $16, $12, SKIP #ASCII<‘A’, do nothing bgt $16, $13, LOWER #else if ASCII>’Z’, not uppercase jal TO_LOWER #else uppercase j SKIP LOWER: blt $16, $14, SKIP # if ‘Z’<ASCII<’a’, neither bgt $16, $15, SKIP #else if ASCII>’z’, neither jal TO_UPPER #else ‘a’<ASCII<’z’, SKIP: jal STORE addi $6, $6, 1 #increment pointer bne $5, $6, loop jal PRINT addi $v0, $0, 10 #exit program syscall TO_LOWER: addi $16, $16, 32 jr $ra #add offset between upper and lower TO_UPPER: addi $16, $16, -32 jr $ra #subtract offset between upper and lower STORE: sw $16, MSG2($6) jr $ra #storing converted number to MSG2 PRINT: la $a0, MSG2 li $v0, 4 syscall jr $ra #putting address of MSG2 to a0 to print #print string system call