MIPS Programming. A basic rule is: try to be mechanical (that is, don't be "tricky") when you translate high-level code into assembler code.

Similar documents
Problem: ! bell! help!! 1! 2!! Bal help!!!! Bal bell! 3 Jr $31!!!! ! Jr $31! What happend! What will happen here?!

Subroutines. int main() { int i, j; i = 5; j = celtokel(i); i = j; return 0;}

Course Administration

COMP 303 Computer Architecture Lecture 3. Comp 303 Computer Architecture

Code Generation. The Main Idea of Today s Lecture. We can emit stack-machine-style code for expressions via recursion. Lecture Outline.

We can emit stack-machine-style code for expressions via recursion

Branch Addressing. Jump Addressing. Target Addressing Example. The University of Adelaide, School of Computer Science 28 September 2015

Compiling Code, Procedures and Stacks

MIPS Functions and the Runtime Stack

Memory Usage 0x7fffffff. stack. dynamic data. static data 0x Code Reserved 0x x A software convention

comp 180 Lecture 10 Outline of Lecture Procedure calls Saving and restoring registers Summary of MIPS instructions

Chapter 2. Computer Abstractions and Technology. Lesson 4: MIPS (cont )

Do-While Example. In C++ In assembly language. do { z--; while (a == b); z = b; loop: addi $s2, $s2, -1 beq $s0, $s1, loop or $s2, $s1, $zero

Functions in MIPS. Functions in MIPS 1

Code Generation. Lecture 12

CS 61c: Great Ideas in Computer Architecture

Computer Architecture

Instruction Set Architectures (4)

Compilers and computer architecture: A realistic compiler to MIPS

Lectures 5. Announcements: Today: Oops in Strings/pointers (example from last time) Functions in MIPS

ECE 30 Introduction to Computer Engineering

Overview. Introduction to the MIPS ISA. MIPS ISA Overview. Overview (2)

EE 361 University of Hawaii Fall

Chapter 2A Instructions: Language of the Computer

MIPS Instruction Set

Chapter 3. Instructions:

Calling Conventions. Hakim Weatherspoon CS 3410, Spring 2012 Computer Science Cornell University. See P&H 2.8 and 2.12

Control Instructions. Computer Organization Architectures for Embedded Computing. Thursday, 26 September Summary

Control Instructions

CSE Lecture In Class Example Handout

ECE232: Hardware Organization and Design

CS61C Machine Structures. Lecture 12 - MIPS Procedures II & Logical Ops. 2/13/2006 John Wawrzynek. www-inst.eecs.berkeley.

Lecture 5: Procedure Calls

Lecture 5. Announcements: Today: Finish up functions in MIPS

Lecture 7: Procedures

Prof. Kavita Bala and Prof. Hakim Weatherspoon CS 3410, Spring 2014 Computer Science Cornell University. See P&H 2.8 and 2.12, and A.

We will study the MIPS assembly language as an exemplar of the concept.

Today. Putting it all together

Machine Language Instructions Introduction. Instructions Words of a language understood by machine. Instruction set Vocabulary of the machine

Function Calling Conventions 1 CS 64: Computer Organization and Design Logic Lecture #9

Implementing Procedure Calls

CS64 Week 5 Lecture 1. Kyle Dewey

Code Generation. Lecture 19

Lecture 2. Instructions: Language of the Computer (Chapter 2 of the textbook)

Chapter 2: Instructions:

CS61C : Machine Structures

ECE260: Fundamentals of Computer Engineering

CS61C : Machine Structures

CS 110 Computer Architecture Lecture 6: More MIPS, MIPS Functions

Chapter 2. Instruction Set Architecture (ISA)

101 Assembly. ENGR 3410 Computer Architecture Mark L. Chang Fall 2009

Stored Program Concept. Instructions: Characteristics of Instruction Set. Architecture Specification. Example of multiple operands

MIPS Functions and Instruction Formats

CS 110 Computer Architecture MIPS Instruction Formats

MIPS function continued

Lecture 5: Procedure Calls

CS 61C: Great Ideas in Computer Architecture More MIPS, MIPS Functions

Chapter 2. Instructions: Language of the Computer. Adapted by Paulo Lopes

Rui Wang, Assistant professor Dept. of Information and Communication Tongji University.

Computer Science 2500 Computer Organization Rensselaer Polytechnic Institute Spring Topic Notes: MIPS Programming

Lab 4 : MIPS Function Calls

CISC 662 Graduate Computer Architecture. Lecture 4 - ISA MIPS ISA. In a CPU. (vonneumann) Processor Organization

CS 61c: Great Ideas in Computer Architecture

Chapter 2. Instructions:

MODULE 4 INSTRUCTIONS: LANGUAGE OF THE MACHINE

SPIM Procedure Calls

Review of Activation Frames. FP of caller Y X Return value A B C

Thomas Polzer Institut für Technische Informatik

Stored Program Concept. Instructions: Characteristics of Instruction Set. Architecture Specification. Example of multiple operands

ECE 30 Introduction to Computer Engineering

CSE Lecture In Class Example Handout

CA Compiler Construction

Lecture Outline. Topic 1: Basic Code Generation. Code Generation. Lecture 12. Topic 2: Code Generation for Objects. Simulating a Stack Machine

CS356: Discussion #6 Assembly Procedures and Arrays. Marco Paolieri

MIPS Assembly (Functions)

The plot thickens. Some MIPS instructions you can write cannot be translated to a 32-bit number

Computer Organization and Structure. Bing-Yu Chen National Taiwan University

ECE 331 Hardware Organization and Design. Professor Jay Taneja UMass ECE - Discussion 3 2/8/2018

The plot thickens. Some MIPS instructions you can write cannot be translated to a 32-bit number

ELEC / Computer Architecture and Design Fall 2013 Instruction Set Architecture (Chapter 2)

CISC 662 Graduate Computer Architecture. Lecture 4 - ISA

Storage in Programs. largest. address. address

CS 61C: Great Ideas in Computer Architecture. MIPS Instruction Formats

Instructions: Assembly Language

MIPS R-format Instructions. Representing Instructions. Hexadecimal. R-format Example. MIPS I-format Example. MIPS I-format Instructions

Inequalities in MIPS (2/4) Inequalities in MIPS (1/4) Inequalities in MIPS (4/4) Inequalities in MIPS (3/4) UCB CS61C : Machine Structures

UCB CS61C : Machine Structures

CSCI 402: Computer Architectures. Instructions: Language of the Computer (3) Fengguang Song Department of Computer & Information Science IUPUI.

CS 316: Procedure Calls/Pipelining

ECE331: Hardware Organization and Design

Common Problems on Homework

MIPS Assembly Language Guide

CS61C : Machine Structures

Instructions: MIPS arithmetic. MIPS arithmetic. Chapter 3 : MIPS Downloaded from:

CS 61C: Great Ideas in Computer Architecture More RISC-V Instructions and How to Implement Functions

Procedures and Stacks

ECE/CS 314 Fall 2003 Homework 2 Solutions. Question 1

EE 109 Unit 15 Subroutines and Stacks

Lab 4 Prelab: MIPS Function Calls

Instructions: MIPS ISA. Chapter 2 Instructions: Language of the Computer 1

Transcription:

MIPS Programming This is your crash course in assembler programming; you will teach yourself how to program in assembler for the MIPS processor. You will learn how to use the instruction set summary to write a program which runs in the MIPS simulator, running in "No Pipe" mode. To write the program, you will need to understand iteration, subroutine calls and parameter passing, recursion, storage and accessing of word and byte arrays, how basic high-level constructs map into assembler code (such as "if - then - else"), some of the differences between signed and unsigned integer arithmetic and comparisons, and many other things as well. A basic rule is: try to be mechanical (that is, don't be "tricky") when you translate high-level code into assembler code. For example, the high-level code (shown here in pseudocode) WHILE [condition] DO ENDWHILE should have this structure in assembler: top_of_while: [if condition is false, branch to "while_escape"] [unconditional branch to "top_of_while"] while_escape: Test-last loops are even simpler: REPEAT UNTIL [condition]; would have this structure in assembler: top_of_repeat: [if condition is false, branch to "top_of_repeat"] Conditional constructs also require a label for the branch target: IF [condition] THEN ENDIF would have this structure in assembler: if_bottom: [if condition is false, branch to "if_bottom"] If-then-else is a little more complicated: IF [condition] THEN [then_body] ELSE [else_body] ENDIF and has this structure in assembler: do_else: [if condition is false, branch to "do_else"] [then_body] [unconditional branch to "if_bottom"] [else_body]

if_bottom: "For"-loops are very similar to the examples given above. Simple assignment statements involve evaluating the right-hand side until you obtain a simple result, and then storing that result into the address of the location designated by the left-hand side. For example A := expression; has this structure in assembler: [compute expression into a simple result] [obtain address of location "A"] [store the result into that address] As you can see from the examples above, you need to use "branch" and "conditional branch" instructions to establish the control structure of your code, and invent "labels" so that your branch instructions can state where they want to branch to. But if you follow the guidelines above for writing structured assembler code, it becomes easy to nest structures inside of each other, and that way you can begin to write very complicated code very quickly. Your biggest problem will be in inventing new "labels", so that all labels have unique names. Subroutine Calls and Parameters There are two extremes in how to pass parameters, and how to allocate local variables within subroutine activations. The first way is: pass the parameters in registers (the MIPS convention says, registers $a0 through $a3 can be used to pass parameters, that is, at most four parameters), let the subroutine return its result (if the subroutine is a function) in registers (the MIPS convention is $v0 and $v1), and allocate local variables by assigning each local variable to a register (for example if we have a local integer variable K, then we could simply say (for example) "let register $t0 be integer K." The advantage of using registers like this, for (almost) everything, is to avoid having to access the primary memory (using memory instructions such as lw, sw etc) which is slower than using just registers. The disadvantage is that there aren't very many registers. What happens if we have 5 parameters? What happens if we have 50 local variables? The other extreme is to only use registers as "scratchpads," that is, to compute temporary results, but to pass parameters, return result, and allocate local variables in the primary memory. A special part of the primary memory is used for this, called the stack. The top-of-stack is identified by reserved register $sp, which points to (that is, which contains the address of) that word in memory which is the topmost word of the stack. To "push" a new word onto the stack, $sp is decremented to make room on the stack, and then the new data value is written into the memory location pointed to by the new contents of $sp. That is, our stack "grows" towards lower addresses. To "pop" from the stack, do the reverse: first read the data, then increment the $sp. There is a single rule for working with the stack: never attempt to access data at a negative offset from register $sp. Consider all those memory locations as "volatile." For example, if you write to -4($sp), and then immediately attempt to read from -4($sp), you may read back something else than what you wrote! The reason for this is exceptions and interrupts which you will learn about later in the course. D0013E Calling Convention The following subroutine convention will be used in this course, and it is a compromise between the two extremes discussed above. parameters are passed in $a0 / $a0-$a1 / $a0-$a1-$a2 etc, any return result(s) are passed back in $v0 / $v0-$v1; subroutines must preserve all the caller's registers except for the $tx and $ax registers, and these should normally be stored on the stack if they are needed after the call; use a "frame pointer" $fp as described below, and learn to allocate local variables in both registers and on the stack. In this course you will do both. By following this convention, the code you write will be naturally recursive (that is, subroutines can call themselves and not become confused). The "frame pointer" ($fp) may appear unnecessary for programs as small as in the one below, but we want you to learn how to use it. Consider the following main program, which calls subroutine "sum": # the main program:

main: li $a0, 5 # set up parameter := 5 bal sum # call: sum( 5 ) # result in $v0 Now we show how "sum" would look, first without a frame pointer, and afterwards with a frame pointer. ============ "sum" without frame pointer =============== ===== code is kind of "tricky" and stack-delicate. ===== # compute sum = n + (n-1)+(n-2)+...+ 1 # call only for n 0. # sum(n: int): int (direct-recursive) # if n = 1 # then return( 1 ) # else return( n + sum(n-1) ); sum: addiu $sp, $sp, -4 # push the return addr... sw $31, 0($sp) #...onto the stack. addiu $sp, $sp, -4 # now push the incoming... sw $a0, 0($sp) #...param "n" if: ori $t0, $zero, 1 # $t0 := 1 bne $a0, $t0, else # n 1, branch to "else" then: ori $v0, $zero, 1 # return value := 1, b exit # to exit sequence. else: addiu $a0, $a0, -1 # compute n-1 (destroys $a0). bal sum # $v0 := sum( n-1 ). # call also wipes out our $31. lw $t0, 0($sp) # fetch our incoming value "n". addu $v0, $v0, $t0 # $v0 := n + sum( n-1 ). exit: lw $31, 4($sp) # restore return address. addiu $sp, $sp, 8 # stack like we found it. jr $31 # return ========== end "sum" without frame pointer ============= However, when writing large subroutines, having many parameters, many local variables, and which may even change $sp during its execution (for example, when using the stack to evaluate a complicated push-down expression that does not fit in the registers) it is difficult to do everything $sp-relative. For that reason we will use a second register $fp (frame pointer) to "mark" a place on the stack. $fp is guaranteed never to change during this activation, so we can rely on it to generate addresses into our activation record: stack-passed parameters (if any) will be at a positive offset from the value in $fp, local variables (if we don't have enough temporary registers, or if we need to save something on the stack) will be at a negative offset relative to the frame pointer (note: we did NOT say, "negative offset from the stack pointer"). Here's an example of how to use the frame pointer. The main program looks exactly the same as above. ============== "sum" with frame pointer ================ ===== example of a subroutine with frame pointer. ===== ===== easier to restore and manage the stack. ===== ===== little bit less efficient code. ===== # ================================== # compute sum = n + (n-1)+(n-2)+...+ 1 # call only for n 0. # sum( n: int ): int (direct-recursive)

# x: int; (example of local variable) # if n = 1 # then return( 1 ) # else return( n + sum(n-1) ); sum: addiu $sp, $sp, -4 sw $31, 0($sp) # push the return addr addiu $sp, $sp, -4 sw $fp, 0($sp) # push the old frame pointer move $fp, $sp addiu $sp, $sp, -8 # establish new frame pointer. # make room for 2 full # word local variables # everything above is called the "entry sequence". # the stack now looks like this. # YOU MUST SHOW US A DIAGRAM LIKE THIS, FOR ALL # THE SUBROUTINES YOU WRITE IN LAB 1. # # uninit, for "x" -8($fp) <= $sp points here # uninit, for "n" -4($fp) # old frame pointer 0($fp) <= $fp points here # our return addr 4($fp) # --+-------------------+-- # # caller's stack # # # (we don't need "x" below, just given as an example.) # now this activation can access its activation record # RELATIVE TO THE FRAME POINTER, like this: save: sw $a0, -4($fp) # save "n" into local var if: ori $t0, $zero, 1 # $t0 := 1 bne $a0, $t0, else # n 1, jump to "else" then: ori $v0, $zero, 1 # n = 1: return value := 1, b exit # escape to exit sequence. else: addiu $a0, $a0, -1 # compute n-1 (destroys $a0). bal sum # $v0 := sum( n-1 ). lw $t0, -4($fp) # fetch value "n". addu $v0, $v0, $t0 # $v0 := n + sum( n-1 ). # the exit sequence reverses the entry sequence: exit: move $sp, $fp # all local var's gone: easy! lw $fp, 0($sp) # restore old $fp addiu $sp, $sp, 4 # and pop that word, lw $31, 0($sp) # restore return address, addiu $sp, $sp, 4 # and pop that word. jr $31 # return =========== end "sum" with frame pointer =============== Remember: The simulator starts executing with the first instruction that you write, so if you want to write your subroutines first, you will have to "jump over" them...

.text j main #...like this. To my main program. sum: # for example, subroutine "sum" above. : jr $ra # end of code for "sum" main: li $a0, 5 bal sum # my main program, that calls "sum" # compute sum(5) # "sum" returns answer in "$v0"