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
Chapter 3: Instructions CS 447 Jason D. Bakos 1 Assembly Language Instructions • We’re going to use the MIPS R2000 instruction set for the projects in this course • Review: Assembly language instructions are English words that represent binary machine language instructions 2 Arithmetic/Logical Instructions • Arithmetic instructions are composed of an operation and three registers – <op> <destreg> <operand1> <operand2> – There are 32 32-bit general-purpose integer registers that we can use (R0 is hardwired to value 0 for A/L operands) – Ex: add $1, $2, $3 • When writing assembly language programs, comments can be added after any instruction by using the ‘#’ character • Some architectures only use 2 registers – The result is stored in the first operand register – Some of our instructions will use this convention • Appendix A in the textbook lists all 3 Immediate Arithmetic/Logical Instructions • Most arithmetic/logical instructions have an “immediate” version – Immediate instructions have an ‘i’ at the end of the instruction name – Immediate instructions allow us to specify an immediate/constant/literal in lieu of a register operand – Ex: add $1, $2, 16 – We only have 16-bits for the immediate, so we can only represent 216 unique values – Use decimal numbers for the immediate value in the assembly-language instruction 4 A/R Instructions • MIPS R2000 A/L-instructions (complete) – – – – – – – – – add, addu, addi, addiu and, andi div, divu (two registers) mult, multu (two registers) nor or, ori sll, sllv, sra, srav, srl, srlv sub, subu xor, xori 5 Pseudoinstructions • Pseudoinstructions are assembled into more than 1 machine instruction – There’s no real machine instruction for them – Ex. abs rdest, rsrc – Assembles into three instructions • move the contents of rsrc into rdest • if rdest is greater than 0, skip over the next instruction – We haven’t covered conditional branches yet • subtract rdest from 0 – Appendix A specifies which are pseudoinstructions 6 Design Considerations • Making most arithmetic instructions have 3 operands simplifies the hardware – This is a design decision – Having a variable number of operands would greatly complicate the hardware • Limiting ourselves to 32 registers is also a design decision to keep things on the processor die smaller – Influences clock cycle time – Gives us more real estate for other things on our core • Less registers, less decoding logic, etc. 7 Registers • MIPS assembly language also has symbolic names for the registers – $0 => constant 0 – $1 => $at (reserved for assembler) – $2,$3 => $v0,$v1 (expression evaluation and results of a function) – $4-$7 => $a0-$a3 (arguments 1-4) – $8-$15 => $t0-$t7 (temporary values) • Used when evaluating expressions that contain more than two operands (partial solutions) • Not preserved across function calls – $16-$23 => $s0->$s7 (for local variables, preserved across function calls) – $24, $25 => $t8, $t9 (more temps) – $26,$27 => $k0, $k1 (reserved for OS kernel) – $28 => $gp (pointer to global area) – $29 => $sp (stack pointer) – $30 => $fp (frame pointer) – $31 => $ra (return address, for branch-and-links) 8 Memory and Load/Store Instructions • As we’ve already seen, a processor can only use data stored in its registers as operands and targets for computation • Typically, before computation can be performed, data must be loaded from main memory • After the computation is complete, the results must be stored back to main memory 9 Memory • Computer memory is byte-addressed but the MIPS architecture requires alignment of loads and stores on the 32-bit (4 byte/word) boundary – This means that all memory references must be an even multiple of 4 • When addressing 4-byte words, you need to provide the address of the lowest-addressed byte in the word 10 Load/Store Instructions • Most commonly used: – lw, sw, lh, sh, lb, sb, la • Use: – lw <rdest>, address – address can be represented as: • symbolic address (that you declare in SPIM) • symbolic address with register index • decimal_offset($basereg) – This is the way that the instruction is translated – loads/stores from contents of $basereg+decimal_offset 11 Load/Store Instructions • SPIM treats loads and stores with symbolic addresses as pseudoinstructions – loads the address of the data segment as an immediate into $1 • lui $1, 4097 – data starts at hex address 10010000 – If an index register is provided, adds the contents of the index reg to $1 • addu $1, $1, rindex – loads 0($1) into rdest • lw rdest, offset_of_variable($1) • This is an example of base-displacement addressing • This is why R1 is reserved when you write your programs 12 Load/Store Instructions • When loading or storing halfwords and bytes, the address points to a aligned word – The halfword would be the LOWER (least significant) halfword of the word that the address is pointing to – The byte world be the LOWEST (least significant) byte of the word being that the address is pointing to 13 Constant-Manipulating Instructions • lui rt, imm – Load the immediate imm into the upper halfword of register rt – The lower bits are set to 0 • li rt, imm – Load the imm into the lower halfword of register rt – The upper bits are set to 0 14 Encoding Instructions • The MIPS architecture has a 32-bit binary instruction format for each class of instruction – A/L, constant manip, comparison, branch, jump, load/store, data movement, floating-point • Even though we’ve only covered 3 of these classes, let’s look at how we encode the instructions we’ve learned… 15 Encoding/Translating A/L Instructions • First (most significant, left-most) 6bits of ALL instructions is the opcode – The opcode defines the instruction – Doesn’t this only give us 26=64 different instructions? • Yes! But all A/L instructions, excluding the ones which have immediates, has an opcode of 0 but has a 6-bit field at the end of the instruction that specifies the operation 16 Encoding/Translating A/L Instructions • Non-immediate A/L instructions: – – – – – – 6 5 5 5 5 6 bits bits bits bits bits bits – – – – – – opcode (usually 0) rs (operand 1) rt (operand 2) rd (destination) 0’s or shift amount operation code 17 Encoding/Translating A/L Instructions • Immediate A/L instructions – – – – 6 bits – opcode (now unique) 5 bits – rs (operand 1) 5 bits – rt (destination) 16 bits – immediate (understood to be 0extended) 18 Encoding/Translating Load/Store Instructions • 6 bits – opcode • 5 bits – rs (base register) • 5 bits – rt (load from/store to) – Sometimes the whole register isn’t used • Half words and bytes • 16 bits – offset 19 Encoding/Translating Constant-Manip. Instructions • 6 bits – opcode • 5 bits – 0’s • 5 bits – rt dest. register – Half of this register will be assigned 0’s • 16 bits – immediate 20 Examples • Let’s compile the following C++ code segment into assembly code: – – z=(a*b)+(c/d)-(e+f*g); lw $s0,a lw $s1,b mult $s0,$s1 mflo $t0 # new instruction lw $s0,c lw $s1,d div $s0,$s1 mflo $t1 add $t0,$t0,$t1 lw $s0,e lw $s1,f lw $s2,g mult $s1,$s2 mflo $t1 add $t1,$s0,$t1 sub $t0,$t0,$t1 sw $t0,z 21 Examples • Note: There were many ways we could have compiled the C++ statement • Now let’s assemble the first three instructions to machine code – Assume the variables are all stored as words and are stored sequencially, starting with a, from the start of the data segment… 22 Examples • lw $s0,a – We know s0 is $16 – There are a few different ways we can do this, too… – First, we need to convert this instruction to a small series of instructions… – lui $1,4097 # 4097 is 1001 in hex lw 16,0($1) # 0 offset because a is first var … 00111100000000010001000000000001 => 3C011001 10001100000100000000000000000000 => 8C100000 23 Examples • mult $s0, $s1 – 00000010000100010000000000011000 => 02110018 24 Branch/Jump Instructions • • Branch and jump instructions are needed for program control – if-statements (conditionals) – loops – procedure calls Most common: – b <label> -- unconditional branch • label is a memory address (we can be symbolic ones, of course) – beq, bgez, bgezal, bgtz, blez, etc. • Conditional branches, where we’re comparing a register to 0 or two registers to determine if we’re going to branch or not • Also have al (and-link) variants, that link a return address (instruction following branch) into $31 so we can return • Branch targets are 16-bit immediate offset – offset in words… it is shifted to the left 2 bits to get byte length 25 Branch/Jump Instructions – j, jal • Unconditionally branches to a 26-bit pseudodirect address (not offset) – jalr, jr • Unconditionally branches to an address stored in a register 26 Encoding/Translating Branch/Jump Instructions • See Appendix A – These are very similar to the encoding we covered before 27 Data Movement and Comparison Instructions and Their Encoding • I’m going to leave the study of these instructions (from Appendix A) up to you as an exercise! 28 Examples • if ((a>b)&&(c=d)) e=0; else e=f; lw $s0,a next0: nope: yup: out: lw $s1,b bgt $s0,$s1,next0 b nope lw $s0,c lw $s1,d beq $s0,$s1,yup lw $s0,f sw $s0,e b out xor $s0,$s0,$s0 sw $s0,e … 29 Examples • Again, there are many other ways we could have tackled this… • You will eventually come up with your own strategies for “compiling” the types of constructs you want to perform… 30 Examples • How about a for loop? • for (i=0;i<a;i++) b[i]=i; lw $s0,a xor $s1,$s1,$s1 loop0: blt $s1,$s0,loop1 b out sll $s2,S1,2 loop1: sw $s1,b($s2) addi $s1,$s1,1 b loop0 out: … 31 Examples • How about a pretest while loop? • while (a<b) { a++; } loop0: loop1: out: lw $s0,a lw $s1,b blt $s0,$s1,loop1 b out addi $s0,Ss0,1 sw $s0,a b loop0 … 32 Examples • How about a posttest while loop? • do { a++; } while (a<b); lw $s0,a lw $s1,b loop0: addi $s0,$s0,1 sw $s0,a blt $s0,$s1,loop0 … 33 Procedure Calls • How about a procedure call? – The full-blown C/Pascal recursive procedure call convention is beyond the scope of this class, so we’ll skip it for now… – This is described in detail in Appendix A • You can arbitrarily implement your own procedure call convention… 34 Procedure Calls • Say we want to write a procedure that computes the factorial of a number, like this: int factorial (int val) { int temp=val; while (val) temp*=(--val); return temp; } 35 Procedure Calls • Let’s adopt the following simple convention: – We’ll pass the arguments through $a0-$a3 • Only allows for up to 4 arguments – We’ll set our return value in $v0 – The return address will be stored in $ra • This limits us to 1-level of procedure calls – We’ll assume the callee (procedure) will save registers $s0-$s7 starting at memory address FF000000 when it’s called, and restore the registers before it returns • This may not be necessary for all procedures 36 Procedure Calls • So here’s our procedure… factorial: loop0: loop1: out: lui $t1,0xFF00 sw $s0,0($t1) sw $s1,4($t1) … sw $s7,28($t1) move $s0,$a0 move $s1,$a0 bgtz $s0,loop1 b out mult $s0,$s1 mflo $s1 subi $s0,$s0,1 b loop0 move $v0,$s1 lw $s0,0($t1) … jr $31 # new instruction # load back registers 37 Procedure Calls • In order to call our procedure… – load a value into $a0 – bal factorial – look in $v0 for the result! 38 I/O • Doing I/O with SPIM is also described in Appendix A, but we’re going to use the system calls that are set up for us to do I/O… 39 I/O • SPIM provides some operating system services through the syscall instruction • To use the system calls: – load system call code (from pg. a49) into $v0 and argument into $a0… – return values in $v0 (or $f0 for fp results) 40 Example I/O str: .asciiz “the answer = “ .text li $v0,4 la $a0, str syscall li $v0,1 la $a0,5 syscall (Refer to page A-49) 41