# Instruction Set Architecture Classification According to the type of internal storage in a processor the basic types are Stack Accumulator General Purpose.

## Presentation on theme: "Instruction Set Architecture Classification According to the type of internal storage in a processor the basic types are Stack Accumulator General Purpose."— Presentation transcript:

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

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

Accumulator One operand implicitly in accumulator, the other in memory and result in accumulator

Register - Memory One operand is in a register the other in memory and the result is stored in a register

Register – Register/ Load – Store Both operands and result are stored in registers

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... 3.1 We give computers orders by means of instructions Instructions tell the computer what it should be doing, right now Arithmetic Logic Data movement Control

Binary review Binary representations of numbers consist of only 1’s and 0’s 0101 2 = 5 10 1000 2 = 8 10 1111111 2 = 127 10 Unsigned (always positive) binary numbers 2 10 = 1024 = 1K  1,000 2 20 = 1,048,576 = 1M  1,000,000 2 30 = 1,073,741,824 = 1G  1,000,000,000 2 10 = 1024 = 1K  1,000 2 20 = 1,048,576 = 1M  1,000,000 2 30 = 1,073,741,824 = 1G  1,000,000,000 Binary Facts:

Converting between binary and hex Binary 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 Group bits together in groups of 4 Assign the appropriate hex digit to each group Done 1000110010110010000111 2 --> 10 0011 0010 1100 1000 0111 2 10 0011 0010 1100 1000 0111 2 --> 2 3 2 C 8 7 = 232C87 16 Hexadecimal 0 1 2 3 4 5 6 7 8 9 A B C D E F

The Translation Process Computers speak in binary. We don’t. A = B + C add\$1, \$2, \$3 000000 00010 00011 00001 00000 100000 Compiler Assembler High-level language Assembly language Machine language Compilers and Assemblers translate from one language to another. 3.2

MIPS Instructions addA, B, C Operation Destination Sources A = B + C subD, A, B D = A - B In MIPS, All register-to-register arithmetic instructions have three operands. In MIPS, All register-to-register arithmetic instructions have three operands. 3.2

Operands addA, 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 MIPS has 32 general-purpose registers \$0 through \$31 47 \$2 3.3 Each register holds 32 bits 0 to 2 32 -1 (4 billion) if unsigned -2 31 to +2 31 -1 (-2 billion to +2 billion) if signed Most registers can hold any value, for any purpose Exception: \$0 is always zero!

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 #NamePurpose \$0\$zeroConstant zero \$1\$atReserved for assembler \$2\$v0Function return value \$3\$v1 \$4\$a0Function parameter \$5\$a1 \$6\$a2 \$7\$a3 \$8\$t0Temporary – Caller-saved \$9\$t1 \$10\$t2 \$11\$t3 \$12\$t4 \$13\$t5 \$14\$t6 \$15\$t7 #NamePurpose \$16\$s0Temporary – Callee-saved \$17\$s1 \$18\$s2 \$19\$s3 \$20\$s4 \$21\$s5 \$22\$s6 \$23\$s7 \$24\$t8Temporary – Caller-saved \$25\$t9 \$26\$k0Reserved for OS \$27\$k1 \$28\$gpGlobal pointer \$29\$spStack pointer \$30\$fpFrame pointer \$31\$raFunction 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. 3.3 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

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 Note: Typically, the compiler assigns variables to registers Note: Typically, the compiler assigns variables to registers \$12 = (\$8 + \$9) - (\$10 + \$11) We don’t have a 5-operand add/subtract instruction! Use temporary variables to solve the problem. add\$13, \$8, \$9# \$13 <-- A + B add\$14, \$10, \$11 # \$14 <-- C + D sub\$12, \$13, \$14# 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. add\$13, \$8, \$9 Assembler 0 8 9 13 0 32 Opcode RS RT RD ShAmt Function 6 bits5 bits 6 bits 0 = Add\$8\$9\$13032=Add 32 bits, total R-Type Instruction 3.4 000000 01000 01001 01101 00000 100000

Staying Regular R-Type instructions all have the same format: Add has an opcode of ‘0’, a function of ‘32’ The instructions differ only in one bit! Regularity: Similar functions should be similar in format. Regularity is a key to high-performance 3.4 Opcode RS RT RD ShAmt Function 6 bits5 bits 6 bits Subtract has an opcode of ‘0’, a function of ‘34’ add \$13,\$8,\$9: 000000 01000 01001 01101 00000 100000 sub \$13,\$8,\$9: 000000 01000 01001 01101 00000 100010

Constants Many times, an instruction needs to use a constant value Multiply by 4 Add 3 I-Type instructions all have the same format: Opcode RS RT Immediate Data 6 bits5 bits 16 bits 8 10 12 4 001000 01010 01100 0000 0000 0000 0100 I-Type Instruction 3.8 add immediate Instructions with constant data in them are called immediate instructions addi \$12, \$10, 4 # Reg. 12 <-- Reg. 10 + 4

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! 3.4 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

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. 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. You need to load a register with a value from memory. lw \$10, 1000(\$0)# copy memory location 1000 to \$10 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 3288 0996 43 1000 234 1004 Afterwards, \$10 has the value 43 44

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) # load M[4500] into \$15 add \$15, \$15, \$3 # add \$3 to \$15 sw \$15, 4500(\$0) # store \$15 back into M[4500] 3.3 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

Data Structures - Arrays A single-dimensional array (vector) is a simple linear data structure 2000 2004 2008 2012 2016 2020 2024 2028 int A[5]; /* integers are 4 bytes each */ start of array (2004 in this example) A[0] A[1] A[2] A[3] A[4] 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 123 6000 3288 6004 43 6008 1 6012 45 6016... Note: Memory addresses refer to 8-bit bytes! We 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. Note: Memory addresses refer to 8-bit bytes! We 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. Move List[0] into \$3: lw \$3, List(\$0) # \$3 <-- List[0] Move List[1] into \$4: addi \$8, \$0, 4 # \$8 <-- 4 lw \$4, List(\$8) # \$4 <-- List[1] addi \$8, \$0, 16 # \$8 <-- 16 lw \$5, List(\$8) # \$5 <-- List[4] Move List[4] into \$5: List and contents of \$8 are added together to form address 3.3 List[0] List[1] List[2] List[3] List[4]

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) Opcode for LW: 35 Think Regularity! 3.4 Opcode RS RT Immediate Data 6 bits5 bits 16 bits 35 9 5 240 100011 01001 00101 0000 0000 1111 0000 I-Type Instruction Opcode for SW: 43 Hmmm, we’ve seen this before....

Assembler directives Somehow, we’ve got to get data into memory User input Involves system calls (we’ll get to that later) Constant data A.10 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.

.word Assembler Directive Buffer:.word01, 02 Label: A name for this memory to go by. Acts as a variable name. Label: A name for this memory to go by. Acts as a variable name..word: Directive to store words in memory here. Data to be stored. 0100 0200 Buffer: Buffer+ 4: lw \$12, Buffer(\$0) # \$12 <-- 00 00 00 01 addi \$10, \$0, 4 # \$10 <-- 4 lw \$13, Buffer(\$10) # \$13 <-- 00 00 00 02 Remember: Words are 4 bytes each! A.10 Loads from Buffer+0Loads from Buffer+4

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. buffer1:.word12 buffer2:.word3, 4, 0x20, 0x5 add\$9, \$0, \$0 firstld:lw\$8, buffer1(\$9) addi\$9, \$9, 4 secld:lw\$10, buffer2(\$9) For this example, assume the location counter starts at 4000 4000: 4004: 4020: 4024: 4028: 4032: 40044008 4012 4016 Hex Constants a denoted by the “0x” prefix buffer1 = 4000 buffer2 = 4004 firstld = 4024 secld = 4032 Label Table Loc. Ctr.

Data Structures? No, thanks Assembly has no concept of “data structures” You can access a “variable” using another “variable”.data Tonto:.word0x44, 0x22 Tonto2:.word 0x32.text main: add\$9, \$0, \$0 # clear \$9 lw\$8, Tonto(\$9) # put Tonto[0] in \$8 addi\$9, \$9, 4 # increment \$9 lw\$10, Tonto(\$9) # put Tonto[1] in \$10 addi\$9, \$9, 4 # increment \$9 lw\$10, Tonto(\$9) # put Tonto[2] ???? in \$10 addi\$v0,\$0,10 syscall

Other Memory Assembler Directives greeting:.asciiz“Resistance is small.” greeting2:.ascii“You will be informed.” 52657369 greeting: 6C652E0... Null-terminated 596F7520 65642E--... greeting2: A.10.byte - reserves bytes in memory.asciiz - reserves Null- terminated ASCII chars.ascii - reserves ASCII characters (no NULL) 10122233 borg: ??18 borg:.byte33, 22, 12, 10, 8, 1

Meeting all your needs for space Sometimes, we need to allocate (empty) space to be used later. inputbuffer:.space100 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\$12, \$0, 6 sw\$12, inputbuffer(\$0) # stores 6 in buffer A.10

Our first program! # This is our first program! Yeah!.data Tonto:.word0x44, 0x22.text main: add\$9, \$0, \$0 # clear \$9 lw\$8, Tonto(\$9) # put Tonto[0] in \$8 addi\$9, \$9, 4 # increment \$9 lw\$10, Tonto(\$9) # put Tonto[1] in \$10 addi\$v0,\$0,10 syscall.data means that data follows.text means that code follows main: tells SPIM where to start these two instructions end the program A.10

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, \$3add\$5, \$3, \$0 neg\$8, \$9sub\$8, \$0, \$9 A.10 li\$8, 44addi\$8, \$0, 44 or ori\$8, \$0, 44

SPIM I/O SPIM I/O uses the SYSCALL pseudoinstruction Set up parameters Place correct code in \$v0 Execute SYSCALL To print the value in \$t3: move \$a0, \$t3 li \$v0, 1 syscall To display a string prompt:.asciiz “hello world” la \$a0,prompt li \$v0, 4 syscall ActionCode (in \$v0)Parameters Print an Integer1\$a0 = value to print Print a String4\$a0 = location of string Input an Integer5(after syscall) \$v0 contains integer Input a String8\$a0 = location of buffer, \$a1 = length Exit program10

Boring Straight-line code is nice, but boring Just arithmetic and loads/stores based on a predetermined sequence A = B+C D = B+F M[18]=D D = B+F D>23? M[22] = D C = B+A Y N 3.5 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

Going places Consider the GoTo if (x == y) q = 13; if (x != y) GoTo Next; q = 13; Next:... while (y < 2) y = y+1; Loop:if (y >=2) GoTo End; y = y+1; GoTo Loop; End:... if (p > q) r = 3; else r=2; if (p>q) GoTo R3; r = 2; GoTo Next; R3:r = 3; Next:... if (condition) GoTo location and GoTo location are all we need 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\$7, \$13, Next beq - Branch if EQual bne - Branch if Not Equal GoTo Exit; jExit j - Jump (unconditionally) Opcode Immediate Data 6 bits26 bits J-Type Instruction 3.5 Branches use I-Type Instruction Format (need two registers and 16-bit data) Jumps need only an opcode and data - There is a lot more room for the data...

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 bne \$x, \$y, False # if \$x != \$y, skip S1 S1# \$x == \$y, execute S1 False:S2# either way we get here, execute S2 3.5 beq \$x, \$y, True # if \$x == \$y, then execute S1 jFalse# \$x != \$y, so exit True:S1# \$x == \$y, execute S1 False:S2# either way we get here, execute S2 If you can’t express the condition as a negative, try this:

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 beq\$x, \$y, IF# if \$x == \$y, goto S1, skip S2 S2 # \$x != \$y, execute S2 jFinish# now execute S3 IF:S1 # \$x == \$y, so execute S1 Finish:S3# 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 bne \$x, \$y, ____ bne \$z, \$w, ____ STEP 2: statements bne \$x, \$y, ____ bne \$z, \$w, ____ S1 S2 S3 STEP 3: branches bne \$x, \$y, false bne \$z, \$w, false S1 j skip false: S2 skip: S3 STEP 1: conditions bne \$x, \$y, ____ bne \$z, \$w, ____ STEP 2: statements bne \$x, \$y, ____ bne \$z, \$w, ____ S1 S2 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 bne \$x, \$y, ____ bne \$z, \$w, ____ STEP 2: statements bne \$x, \$y, ____ bne \$z, \$w, ____ S1 S2 S3 STEP 1: conditions bne \$x, \$y, ____ bne \$z, \$w, ____ STEP 3: branches bne \$x, \$y, false bne \$z, \$w, false S1 j skip false: S2 skip: S3 STEP 1: conditions bne \$x, \$y, ____ bne \$z, \$w, ____ STEP 1: conditions bne \$x, \$y, ____ bne \$z, \$w, ____ STEP 2: statements bne \$x, \$y, ____ bne \$z, \$w, ____ S1 S2 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, ____ bne \$z, \$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 skip: S3 STEP 1: conditions bne \$x, \$y, ____ bne \$z, \$w, ____ STEP 1: conditions beq \$x, \$y, ____ beq \$z, \$w, ____ beq \$x, \$z, ____ beq \$y, \$w, ____ STEP 2: statements beq \$x, \$y, ____ beq \$z, \$w, ____ beq \$x, \$z, ____ beq \$y, \$w, ____ S1 S2 S3

While Loops while \$x == \$y do S1 Execute S1 repeatedly as long as \$x == \$y is true Repeat:bne\$x,\$y, Exit# exit if \$x != \$y is False S1# execute body of loop jRepeat# do it all over again Exit:# end of the loop 3.5 Repeat:S1# execute body of loop beq\$x,\$y, Repeat# do it again if \$x == \$y Exit:# end of the loop Warning: The following loop always executes at least once, no matter what \$x and \$y are:

For Loops for i = \$start to \$finish {S1} S2 Execute S1 for all values from \$start to \$finish (step of 1) move\$t0, \$start# copy start to i (\$t0) Loop:bgt\$t0, \$finish, done# if i > finish, then we’re done - do S2 S1# execute S1 addi\$t0, \$t0, 1# increment count jLoop# go again done:S2 3.5 Use temporary, \$t0 to hold i Note: bgt doesn’t really exist - more on that later...

Other conditions slt\$4, \$10, \$11 Set \$4 = 1 if (\$10 < \$11), otherwise \$4 = 0 if (\$7 < \$8) then \$15 = 3; slt\$1, \$7, \$8# \$1 <-- (\$7 < \$8) beq\$1, \$0, GoOn# If not less than, go on addi\$15, \$0, 3# (\$7 < \$8), so \$15 <-- 3 GoOn: Set on Less Than if (\$12 >= \$3) then \$4 = \$2; slt\$1, \$12, \$3# \$1 <-- (\$12 < \$3) bne\$1, \$0, GoOn# If less than, go on add\$4, \$2, \$0# (\$12 >= \$13), so \$4 = \$2 GoOn: 3.5 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) Example: \$12=4, \$3=2 \$1 = 0 ( \$12 > \$3) \$1 == 0, Don’t branch Set \$4 to 2

Pseudoinstructions for branches Branches can be nasty to figure out SPIM provides several pseudoinstructions for branches blt\$3, \$4, destslt\$1, \$3, \$4 bne\$1, \$0, dest bgt\$3, \$4, destslt\$1, \$4, \$3 bne\$1, \$0, dest \$3 > \$4 same as \$4 < \$3 A.10 ble\$3, \$4, destslt\$1, \$4, \$3 beq\$1, \$0, dest bge\$3, \$4, destslt\$1, \$3, \$4 beq\$1, \$0, dest \$3 >= \$4 is the opposite of \$3 < \$4 \$3 \$4

Branch limitations A conditional branch (BEQ, BNE) uses an I-type Instruction Allows a 16-bit immediate operand 2 16 = 64K Locations is too small 3.8 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)

Branch example loop:bgt\$t0, \$t1, bigger lw\$s0, 0(\$t0) addi\$t0, \$t0, 1 beq\$s0, \$s1, loop bigger:move\$s2, \$t0 8000loop:slt\$1, \$8, \$9 8004bne\$1, \$0, bigger 510+3 8004 0891042 8000 3.8 358160 8008 8881 8012 41617-5 8016 08018032 8020 bigger: + 3 instructions 8020bigger:add\$18, \$8, \$0 8008lw\$16, 0(\$8) 8012addi\$8, \$8, 1 8016beq\$16, \$17, loop loop: -5 instructions +3 -5 Branches: offset is in instructions from the instruction following the branch Note: Negative numbers require 2’s complement

Jump Addressing 3.8 Jumps use a J-type instruction and have a 26-bit offset A lot more range than 16-bit branches Allows a range of 2 26 =64M possibilites 2000:jtarget 0241032 2004 2501 2000 2004: target:add\$1, \$2, \$4 501 = 2004/4 Example: 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

Jumping based on Registers Jumps change the PC to a fixed location j OverThere Always goes to the same place JR - Jump Register 3.5 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

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 lui \$8, 0x1A2B li\$8, 0x3C4D Warning: Don’t use addi for the second instruction; use LI or ORI. (Sign Extension) 3.8 \$8: ---- 3116150 ---- 1A2B 0000 3C4D Put the constant 0x1A2B3C4D in register \$8 We can let the assembler do the work: li \$8, 0x1A2B3C4D will be converted to these two instructions

Getting around branch limitations Branches have a limit of +/- 2 15 instructions - How can we branch further? Use the larger range of the jump instruction: 1000:beq\$s0,\$t1,far 1004:sub\$s2, \$v0, \$a0 … 500000:far:add\$t1, \$t2, \$t3 1000:bne\$s0,\$t1,stay 1004:jfar 1008:stay:sub \$s2, \$v0, \$a0 … 500000:far:add\$t1, \$t2, \$t3 3.8 Can’t branch that far...

Example InstructionR5R6R7 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 #decrement stack pointer sw \$5, 0(\$sp)#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) 3.6 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

InstructionR5R6R7 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) 3.6 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

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, \$9, 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 numbers read from the keyboard, stores it to memory location max and prints the result on the screen. Use functions..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 main: 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:addi \$6, \$0, 5#set loop counter to 5 addi \$7, \$0, 0#set pointer to zero REPEAT:lw \$5, ARRAY(\$7) bge \$8, \$5, SKIP #if \$8 > \$5, keep current maximum move \$8, \$5 #else new maximum SKIP: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 OUTPUT: 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#set loop counter to 5 addi \$6, \$0, 0#set pointer to zero add \$7, \$0, \$0#U add \$8, \$0, \$0#L add \$9, \$0, \$0#D li \$10, 48#0 li \$11, 57#9 li \$12, 65#A li \$13, 90#Z li \$14, 97#a li \$15, 122#z

REPEAT: lb \$16, ARRAY(\$6) blt \$16, \$10, SKIP# if ASCII<’0’, neither bgt \$16, \$11, LETTER #else if ASCII>’9’, not a number addi \$9, \$9, 1#else ‘0’<ASCII<‘9’, it’s a number j SKIP LETTER: blt \$16, \$12, SKIP#if 9<ASCII<‘A’, neither bgt \$16, \$13, LOWER #else if ASCII>’Z’, not uppercase addi \$7, \$7, 1#else 9<ASCII<‘A’, uppercase j SKIP LOWER: blt \$16, \$14, SKIP# if ‘Z’<ASCII<’a’, neither bgt \$16, \$15, SKIP#else if ASCII>’z’, neither addi \$8, \$8, 1#else ‘a’<ASCII<’z’, j SKIP SKIP: addi \$6, \$6, 1 bne \$5, \$6, REPEAT

sw \$7, U(\$0) sw \$8, L(\$0) sw \$9, D(\$0) addi \$v0, \$0, 10#exit program syscall

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 #decrement stack pointer sw \$t1, 0(\$sp)#push x=\$t1 to stack jr \$ra

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 #add offset between upper and lower jr \$ra TO_UPPER: addi \$16, \$16, -32 #subtract offset between upper and lower jr \$ra STORE: sw \$16, MSG2(\$6)#storing converted number to MSG2 jr \$ra PRINT: la \$a0, MSG2#putting address of MSG2 to a0 to print li \$v0, 4#print string system call syscall jr \$ra

Similar presentations