Data Structure Layout. In HERA/Assembly

Similar documents
CSCI-1200 Data Structures Fall 2017 Lecture 5 Pointers, Arrays, & Pointer Arithmetic

MIPS Functions and Instruction Formats

SPIM Procedure Calls

Run-time Environment

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

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

CSE Lecture In Class Example Handout

Implementing Procedure Calls

CSE Lecture In Class Example Handout

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

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

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

Ch. 11: References & the Copy-Constructor. - continued -

Control Instructions

Functions in MIPS. Functions in MIPS 1

Course Administration

Stacks and Function Calls

Implementing Functions at the Machine Level

ECE260: Fundamentals of Computer Engineering

System Software Assignment 1 Runtime Support for Procedures

Announcements HW1 is due on this Friday (Sept 12th) Appendix A is very helpful to HW1. Check out system calls

CSCI-1200 Data Structures Fall 2018 Lecture 5 Pointers, Arrays, & Pointer Arithmetic

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

Computer Architecture

Today. Putting it all together

Code Generation. Lecture 12

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

Code Generation. Lecture 19

Lecture 5: Procedure Calls

CSCI-1200 Data Structures Spring 2017 Lecture 5 Pointers, Arrays, Pointer Arithmetic

Plan. Regression testing: Demo of how to use the regress.sh script.

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

Computer Architecture Prof. Mainak Chaudhuri Department of Computer Science & Engineering Indian Institute of Technology, Kanpur

Chapter 2. Instructions:

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

Compilers CS S-08 Code Generation

CSC 8400: Computer Systems. Using the Stack for Function Calls

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

Compilers and computer architecture: A realistic compiler to MIPS

CS61C : Machine Structures

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

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

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

Lecture 4 September Required reading materials for this class

CSC 2400: Computing Systems. X86 Assembly: Function Calls"

Function Calls COS 217. Reading: Chapter 4 of Programming From the Ground Up (available online from the course Web site)

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

CSCI-1200 Data Structures Spring 2014 Lecture 5 Pointers, Arrays, Pointer Arithmetic

! What do we care about? n Fast program execution. n Efficient memory usage. n Avoid memory fragmentation. n Maintain data locality

Procedure Call. Procedure Call CS 217. Involves following actions

CS61C : Machine Structures

What the CPU Sees Basic Flow Control Conditional Flow Control Structured Flow Control Functions and Scope. C Flow Control.

Instructions: Assembly Language

Math 230 Assembly Programming (AKA Computer Organization) Spring 2008

6.035 Project 3: Unoptimized Code Generation. Jason Ansel MIT - CSAIL

Chapter 10 Memory Model for Program Execution. Problem

Run-time Environments

Run-time Environments. Lecture 13. Prof. Alex Aiken Original Slides (Modified by Prof. Vijay Ganesh) Lecture 13

MIPS Datapath. MIPS Registers (and the conventions associated with them) MIPS Instruction Types

Run-time Environments

CSC 2400: Computing Systems. X86 Assembly: Function Calls

Part 7. Stacks. Stack. Stack. Examples of Stacks. Stack Operation: Push. Piles of Data. The Stack

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.

CSCE 5610: Computer Architecture

Lecture 5: Procedure Calls

CS 61C: Great Ideas in Computer Architecture. (Brief) Review Lecture

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

Assignment 11: functions, calling conventions, and the stack

CSc 520 Principles of Programming Languages. Questions. rocedures as Control Abstractions... 30: Procedures Introduction

CMSC 313 COMPUTER ORGANIZATION & ASSEMBLY LANGUAGE PROGRAMMING

Procedures and Stacks

ECE331: Hardware Organization and Design

Topic 7: Activation Records

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

Data Transfer Instructions

Computer Architecture. The Language of the Machine

Math 230 Assembly Programming (AKA Computer Organization) Spring MIPS Intro

MIPS Functions and the Runtime Stack

Programming the ARM. Computer Design 2002, Lecture 4. Robert Mullins

Storage in Programs. largest. address. address

Contents. Slide Set 2. Outline of Slide Set 2. More about Pseudoinstructions. Avoid using pseudoinstructions in ENCM 369 labs

CS558 Programming Languages

Chapter 3. Instructions:

Assembly labs start this week. Don t forget to submit your code at the end of your lab section. Download MARS4_5.jar to your lab PC or laptop.

ENGN1640: Design of Computing Systems Topic 03: Instruction Set Architecture Design

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

CS153: Compilers Lecture 8: Compiling Calls

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

CPS311 Lecture: Procedures Last revised 9/9/13. Objectives:

Stacks and Frames Demystified. CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han

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

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.

CS 61c: Great Ideas in Computer Architecture

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

CS 61C: Great Ideas in Computer Architecture Strings and Func.ons. Anything can be represented as a number, i.e., data or instruc\ons

1. Number Conversions [8 marks]

CS558 Programming Languages Winter 2018 Lecture 4a. Andrew Tolmach Portland State University

Instruction Set Architectures Part I: From C to MIPS. Readings:

CS61C : Machine Structures

Transcription:

Data Structure Layout In HERA/Assembly

Today, we re going to build some data structures in HERA

First, a note on memory

Registers are very fast RAM is relatively slow We use a cache to sit between them

8-core Haswell chip

Why can t you just do everything in registers?

Here s the moral of today s lecture

You could, but it would be pretty slow. Smart programming is about knowing when to use one vs. the other

One nice thing about C/C++ is that the compiler is very good at making these kinds of decisions for you

One mistake I made from yesterday

HERA organizes memory into words, two-byte sequences

So I said you would STORE(Rd,0,Rb) and Rb = 2 0x06 0x04 0x02 0x00

But I was wrong, it turns out you would use 1 0x06 0x04 0x02 0x00

HERA automatically multiplies all of your indices by 2

Let s start with a binary tree

In C++ struct BinaryTree { int value; BinaryTree *left; BinaryTree *right; }

2 bytes Index Value Int 0 Left BinaryTree * 1 Right BinaryTree * 2

Use NULL (0) to indicate empty pointer

Your job, use INTEGER to create a binary tree containing 42. Label the tree root

Now consider this binary tree

42 13 63

Build this binary tree Use INTEGER and labels 42 13 63

Functions

Implemented a variety of ways. The simplest way is to pass/return args/result in registers For now, don t worry about returning from the function

int getvalue(binarytree *t) { return t->value; } // Assume R1 contains the tree // Result placed in R2 LABEL(getValue) LOAD(R2, 0, R1) Note: the programmer using this has to know the input / outputs

Figure out how to call that function

Now, how do we return from our function?

Answer: pass a pointer to the next instruction when you call it (Use a HERA label)

I want you to get the value, and then next I want you to go to label aftergetvalue

// Assume R1 contains the tree // Assume R2 contains next instr // Result placed in R3 LABEL(getValue) LOAD(R3, 0, R1) BR(R2)

Your assignment Call this function, pass in a label to next instruction, then add one to the result

Alternatively: instead of passing in label to return to, pass in offset (1+current instruction) (We ll see how to use this later..)

Alternatively: instead of passing in label to return to, pass in offset (1+current instruction) HERA convention: use temporary register, Rt/ R13

setleft sets the left child to some value setleft(t,node) Assignment: write setleft

Functions I call can corrupt my registers

Consider the following code

// Assume R1 contains the tree // Assume R2 contains next instr // Result placed in R3 LABEL(getValue) LOAD(R3, 0, R1) SET(R4, 0) BR(R2) This overwrites R4 So if caller using R4, this fails

A non-contrived example

int sumtree(binarytree *t) { if (t == NULL) { return 0; } else { return sumtree(t->left) + sumtree(t->right) + sumtree(t->value); } }

Attempt 1 int sumtree(binarytree *t) { if (t == NULL) { return 0; } else { return sumtree(t->left) + sumtree(t->right) + sumtree(t->value); } } Does not work! // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

Let s see why, using this tree (Encoded in HERA ) 42 13 63

a2 R1 = a1 R2 R3 R4 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = a1 R2 R3 R4 = 42 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = a2 R2 R3 R4 = 42 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = a2 R2 = after1 R3 R4 = 42 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = a2 R2 = after1 R3 R4 = 42 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = a2 R2 = after1 R3 R4 = 42 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = a2 R2 = after1 R3 R4 = 42 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = a2 R2 = after1 R3 R4 = 13 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = 0 R2 = after1 R3 R4 = 13 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = 0 R2 = after1 R3 R4 = 13 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = 0 R2 = after1 R3 R4 = 13 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = 0 R2 = after1 R3 = 0 R4 = 13 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = 0 R2 = after1 R3 = 0 R4 = 13 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = 0 R2 = after1 R3 = 0 R4 = 13 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = 0 R2 = after1 R3 = 0 R4 = 13 a1 42 13 a3 63 // Assume t is in R1 // Assume return addr in R2 // Return result in R3 LABEL(sumTree) SUB(R0,R0,R1) BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) LOAD(R1, 1, R1) SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) ADD(R4,R3,R4) MOVE(R3,R4) BR(R2)

a2 R1 = 0 // Assume t is in R1 R2 = after1 // Assume return addr in R2 // Return result in R3 R3 = 0 LABEL(sumTree) SUB(R0,R0,R1) R4 = 13 BNZ(not_null) SET(R3, 0) BR(R2) LABEL(not_null) LOAD(R4, 0, R1) Segmentation 42 LOAD(R1, 1, fault R1) a1 SET(R2, after1) BR(sumTree) LABEL(after1) ADD(R4,R3,R4) LOAD(R1, 2, R1) SET(R2, after2) BR(sumTree) LABEL(after2) a3 ADD(R4,R3,R4) MOVE(R3,R4) BR(R2) 13 63

So What went wrong?

I assumed my locals were my own

Which registers does sumtree overwrite?

Which registers does sumtree overwrite? R1 R2 R3 R4

So, how do we fix this?

Use the stack

I need to save my registers when I call functions

Note: in HERA, unlike some other processors, the stack grows up Stack (This is different than my i7) top of the stack

We can use a pointer to hold a reference to the top of the stack This is typically called the stack pointer The stack pointer points at the next available word on the stack

Stack SP, aka R15

The stack pointer by convention Stack always points at the top of the stack You can change it, nothing stops you It s just a regular register SP, aka R15

Stack I want to make myself some space for some local variables SP, aka R15

Stack So how do we do that? SP, aka R15

We increment the stack pointer

ADD(SP, 4, SP) SP/R15 Stack Stack frame

Stack Frame: portion of stack that holds local variables for single invocation of some function

By convention we use a frame pointer to refer to the base of the frame

SP/R15 Stack Local variable 4 Local variable 3 Local variable 2 Local variable 1 FP/R14

Frame pointer is handy because I can now use LOAD(Rd, o, FP) To load from local variable o STORE(Rb, o, FP) To store into local variable o

This generalizes to caller-save convention To call a function

This generalizes to caller-save convention To call a function Caller passes arguments on the stack

This generalizes to caller-save convention To call a function Caller passes arguments on the stack Saves registers before call (Also save old SP, FP, and ret. addr)

This generalizes to caller-save convention To call a function Caller passes arguments on the stack Saves registers before call (Also save old SP, FP, and ret. addr) Result returned on the stack

The Big Rule

If I m going to change a register, I had better save it first

I have two possibilities: Either the caller saves the registers Args passed in registers ( Caller save ) Or the callee saves the registers Args passed on stack ( Callee save )

Caller save

Here s what I do

Let s say I m currently using R4 and R5 And foo expects R4/R5 as arguments

R4 23 R5 89

R4 23 R5 89 And my stack looks like this

R4 23 R5 89 Stack And my stack looks like this SP, aka R15

R4 23 R5 89 First: save stack pointer in frame pointer Stack SP, aka R15

FP a R4 23 R5 89 Stack MOVE(FP,SP) SP, aka R15 a

FP a R4 23 R5 89 Stack Next: increment SP SP, aka R15 a

FP a R4 23 R5 89 Stack INC(SP,2) SP, aka R15 a

FP a R4 23 R5 89 Stack INC(SP,2) SP, aka R15 a

FP a R4 23 R5 89 Stack INC(SP,2) This is my new space SP, aka R15 a

Next: save R4 and R5 there

FP a R4 23 R5 89 Stack STORE(R4,0,FP) a

FP a R4 23 R5 89 Stack STORE(R4,0,FP) a 23

FP a R4 23 R5 89 Stack STORE(R5,1,FP) 89 a 23

FP a R4 23 R5 89 Stack Now move args to R4/R5 89 a 23

FP a R4 42 R5 13 Stack SET(R4,42) SET(R5,13) Now move args to R4/R5 89 a 23

FP a R4 42 R5 13 Stack Now I m ready to call foo! 89 a 23

FP a R4 42 R5 13 Stack Then foo does its work 89 a 23

FP a R4 10 R5 13 Stack Assume it returns result in R4 89 a 23

FP a R4 10 R5 13 Stack Now I need to decrement SP 89 a 23

FP a R4 10 R5 13 Stack Now I need to decrement SP SUB(SP,2,SP) SP a

Note: when we call a function, we may also need to save three other registers Stack pointer Frame pointer Return address

Note: when we call a function, we may also need to save three other registers Stack pointer Frame pointer Return address Remember, I m going to increment the stack pointer

Note: when we call a function, we may also need to save three other registers Stack pointer If I didn t, I d forget where the stack was Frame pointer Return address

Note: when we call a function, we may also need to save three other registers Stack pointer If I didn t, I d forget where the stack was Frame pointer Return address I m going to add a frame, too

Note: when we call a function, we may also need to save three other registers Stack pointer If I didn t, I d forget where the stack was Frame pointer If I didn t, I d forget where the frame was Return address I m going to update the return address

Note: when we call a function, we may also need to save three other registers Stack pointer If I didn t, I d forget where the stack was Frame pointer If I didn t, I d forget where the frame was Return address If I didn t, I d forget where to go next

CALL and RETURN instructions

CALL(Ra,Rb) Calls function at address Rb with new stack frame starting at Ra Typically you will use the current SP for Ra

CALL(Ra,Rb) PC R b R b PC + 1 FP R a R a FP

So CALL handles all of the common things to save FP/SP/RT and then set the frame pointer appropriately

Caller save

Code using foo Definition of foo MOVE(FP,SP) INC(SP,1) STORE(R4,0,FP) SET(R2,foo) CALL(SP,R2) LOAD(R4,0,FP) SUB(SP,1,SP) LABEL(getValue) LOAD(R3, 0, R1) SET(R4, 0) BR(R2) RETURN()

Callee save

In callee save, arguments are passed on stack, and result returned on stack

int two_x_plus_y(int x, int y) { } return x+x+y;

This is how I m going to call two_x_plus_y

SP Next word on stack

SP Next word on stack FP+4 FP+3 FP+2 FP+1 FP

SP Next word on stack FP+4 FP+3 2 FP+2 FP+1 FP

SP Next word on stack FP+4 10 FP+3 2 FP+2 FP+1 FP

SP Next word on stack FP+4 10 two_x_plus_y receives this FP+3 2 FP+2 FP+1 FP

Let s dive into this code

What we ve got now.. SP Next word on stack FP+4 Value of y FP+3 Value of x FP+2 Unused FP+1 Unused FP Unused

SP Next word on stack FP+4 Value of arg y FP+3 Value of arg x FP+2 Unused FP+1 Caller s FP FP Return addr

two_x_plus_y wants to use R1 and R2 So make space by incrementing SP SP Next word on stack FP+4 Value of arg y FP+3 Value of arg x FP+2 Unused FP+1 Caller s FP FP Return addr

SP Next word on stack FP+6 Space to save R2 FP+5 Space to save R1 FP+4 Value of arg y INC(SP,2) FP+3 Value of arg x FP+2 Unused FP+1 Caller s FP FP Return addr

SP Next word on stack FP+6 Previous R2 FP+5 Previous R1 FP+4 Value of arg y FP+3 Value of arg x FP+2 Unused FP+1 Caller s FP FP Return addr

SP Next word on stack FP+6 Previous R2 R1 x FP+5 Previous R1 R2 y FP+4 Value of arg y FP+3 Value of arg x FP+2 Unused FP+1 Caller s FP FP Return addr

SP Next word on stack FP+6 Space to save R2 R1 ans FP+5 Space to save R1 R2 y FP+4 Value of arg y FP+3 Return value (ans) FP+2 Unused FP+1 Caller s FP FP Return addr

SP Next word on stack FP+6 Space to save R2 R1 FP+5 FP+5 Space to save R1 FP+4 Value of arg y R2 FP+6 FP+3 Return value (ans) FP+2 Unused FP+1 Caller s FP FP Return addr

R1 FP+5 SP Next word on stack FP+4 Value of arg y R2 FP+6 FP+3 Return value (ans) FP+2 Unused FP+1 Caller s FP FP Return addr

Now caller clears these by decrementing SP SP Next word on stack FP+4 Value of arg y FP+3 Return value (ans) FP+2 Unused FP+1 Caller s FP FP Return addr

So which one should you use?

You could mix and match

Much better to pick one and stick to it

One big reason: if other code wants to interact with your code, you need a common calling convention

The ABI defines your calling convention

Application Binary Interface

If functions use the same ABI, they can work even if they were written in different languages

For example, mixing C and C++

Or call assembly from C++ (This is useful for high-performance apps)