Data Structure Layout In HERA/Assembly Today, were going to build - - PowerPoint PPT Presentation

data structure layout
SMART_READER_LITE
LIVE PREVIEW

Data Structure Layout In HERA/Assembly Today, were going to build - - PowerPoint PPT Presentation

Data Structure Layout In HERA/Assembly Today, were 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 cant you


slide-1
SLIDE 1

Data Structure Layout

In HERA/Assembly

slide-2
SLIDE 2

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

slide-3
SLIDE 3

First, a note on memory

slide-4
SLIDE 4

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

slide-5
SLIDE 5

8-core Haswell chip

slide-6
SLIDE 6
slide-7
SLIDE 7
slide-8
SLIDE 8

Why can’t you just do everything in registers?

slide-9
SLIDE 9

Here’s the moral of today’s lecture…

slide-10
SLIDE 10

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

slide-11
SLIDE 11

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

  • f decisions for you
slide-12
SLIDE 12

One mistake I made from yesterday

slide-13
SLIDE 13

HERA organizes memory into words, two-byte sequences

slide-14
SLIDE 14

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

slide-15
SLIDE 15

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

slide-16
SLIDE 16

HERA automatically multiplies all of your indices by 2

slide-17
SLIDE 17

Let’s start with a binary tree

slide-18
SLIDE 18

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

slide-19
SLIDE 19

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

slide-20
SLIDE 20

Use NULL (0) to indicate empty pointer

slide-21
SLIDE 21

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

slide-22
SLIDE 22

Now consider this binary tree

slide-23
SLIDE 23

42 13 63

slide-24
SLIDE 24

42 13 63

Build this binary tree Use INTEGER and labels

slide-25
SLIDE 25

Functions

slide-26
SLIDE 26

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

slide-27
SLIDE 27

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

int getValue(BinaryTree *t) { return t->value; }

Note: the programmer using this has to know the input / outputs

slide-28
SLIDE 28

Figure out how to “call” that function

slide-29
SLIDE 29

Now, how do we return from

  • ur function?
slide-30
SLIDE 30

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

slide-31
SLIDE 31

“I want you to get the value, and then next I want you to go to label afterGetValue”

slide-32
SLIDE 32

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

slide-33
SLIDE 33

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

slide-34
SLIDE 34

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

slide-35
SLIDE 35

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

slide-36
SLIDE 36

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

slide-37
SLIDE 37
slide-38
SLIDE 38

Functions I call can corrupt my registers

slide-39
SLIDE 39

Consider the following code…

slide-40
SLIDE 40

// 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

slide-41
SLIDE 41

A non-contrived example…

slide-42
SLIDE 42

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

slide-43
SLIDE 43

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

Attempt 1 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)

slide-44
SLIDE 44

42 13 63

Let’s see why, using this tree…

(Encoded in HERA…)

slide-45
SLIDE 45

42 13 63

R1 = a1 R2 R3 R4 a1 a2 a3

// 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)

slide-46
SLIDE 46

42 13 63

R1 = a1 R2 R3 R4 = 42 a1 a2 a3

// 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)

slide-47
SLIDE 47

42 13 63

R1 = a2 R2 R3 R4 = 42 a1 a2 a3

// 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)

slide-48
SLIDE 48

42 13 63

R1 = a2 R2 = after1 R3 R4 = 42 a1 a2 a3

// 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)

slide-49
SLIDE 49

42 13 63

R1 = a2 R2 = after1 R3 R4 = 42 a1 a2 a3

// 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)

slide-50
SLIDE 50

42 13 63

R1 = a2 R2 = after1 R3 R4 = 42 a1 a2 a3

// 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)

slide-51
SLIDE 51

42 13 63

R1 = a2 R2 = after1 R3 R4 = 42 a1 a2 a3

// 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)

slide-52
SLIDE 52

42 13 63

R1 = a2 R2 = after1 R3 R4 = 13 a1 a2 a3

// 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)

slide-53
SLIDE 53

42 13 63

R1 = 0 R2 = after1 R3 R4 = 13 a1 a2 a3

// 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)

slide-54
SLIDE 54

42 13 63

R1 = 0 R2 = after1 R3 R4 = 13 a1 a2 a3

// 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)

slide-55
SLIDE 55

42 13 63

R1 = 0 R2 = after1 R3 R4 = 13 a1 a2 a3

// 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)

slide-56
SLIDE 56

42 13 63

R1 = 0 R2 = after1 R3 = 0 R4 = 13 a1 a2 a3

// 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)

slide-57
SLIDE 57

42 13 63

R1 = 0 R2 = after1 R3 = 0 R4 = 13 a1 a2 a3

// 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)

slide-58
SLIDE 58

42 13 63

R1 = 0 R2 = after1 R3 = 0 R4 = 13 a1 a2 a3

// 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)

slide-59
SLIDE 59

42 13 63

R1 = 0 R2 = after1 R3 = 0 R4 = 13 a1 a2 a3

// 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)

slide-60
SLIDE 60

// 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)

42 13 63

R1 = 0 R2 = after1 R3 = 0 R4 = 13 a1 a2 a3

Segmentation fault

slide-61
SLIDE 61

So… What went wrong?

slide-62
SLIDE 62

I assumed my locals were my own

slide-63
SLIDE 63

Which registers does sumTree overwrite?

slide-64
SLIDE 64

Which registers does sumTree overwrite? R1 R2 R3 R4

slide-65
SLIDE 65

So, how do we fix this?

slide-66
SLIDE 66

Use the stack

slide-67
SLIDE 67

I need to save my registers when I call functions

slide-68
SLIDE 68

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

slide-69
SLIDE 69

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

slide-70
SLIDE 70

Stack … SP, aka R15 …

slide-71
SLIDE 71

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

slide-72
SLIDE 72

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

slide-73
SLIDE 73

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

slide-74
SLIDE 74

We increment the stack pointer

slide-75
SLIDE 75

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

slide-76
SLIDE 76

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

slide-77
SLIDE 77

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

slide-78
SLIDE 78

Stack … SP/R15

Local variable 1 Local variable 2 Local variable 3 Local variable 4

FP/R14

slide-79
SLIDE 79

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

slide-80
SLIDE 80

This generalizes to caller-save convention To call a function…

slide-81
SLIDE 81

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

slide-82
SLIDE 82

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

slide-83
SLIDE 83

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

slide-84
SLIDE 84

The Big Rule

slide-85
SLIDE 85

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

slide-86
SLIDE 86

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

slide-87
SLIDE 87

Caller save

slide-88
SLIDE 88

Here’s what I do

slide-89
SLIDE 89

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

slide-90
SLIDE 90

R4 23 R5 89

slide-91
SLIDE 91

And my stack looks like this… R4 23 R5 89

slide-92
SLIDE 92

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

slide-93
SLIDE 93

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

slide-94
SLIDE 94

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

slide-95
SLIDE 95

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

slide-96
SLIDE 96

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

slide-97
SLIDE 97

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

slide-98
SLIDE 98

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

slide-99
SLIDE 99

Next: save R4 and R5 there

slide-100
SLIDE 100

Stack R4 23 R5 89 FP a

STORE(R4,0,FP)

a

slide-101
SLIDE 101

Stack 23 R4 23 R5 89 FP a

STORE(R4,0,FP)

a

slide-102
SLIDE 102

Stack 23 89 R4 23 R5 89 FP a

STORE(R5,1,FP)

a

slide-103
SLIDE 103

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

slide-104
SLIDE 104

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

slide-105
SLIDE 105

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

slide-106
SLIDE 106

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

slide-107
SLIDE 107

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

slide-108
SLIDE 108

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

slide-109
SLIDE 109

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

slide-110
SLIDE 110

Note: when we call a function, we may also need to save three other registers…

  • Stack pointer
  • Frame pointer
  • Return address
slide-111
SLIDE 111

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

slide-112
SLIDE 112

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
slide-113
SLIDE 113

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…

slide-114
SLIDE 114

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…

slide-115
SLIDE 115

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
slide-116
SLIDE 116

CALL and RETURN instructions

slide-117
SLIDE 117

CALL(Ra,Rb)

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

slide-118
SLIDE 118

CALL(Ra,Rb)

PC ← Rb Rb ← PC + 1 FP ← Ra Ra ← FP

slide-119
SLIDE 119

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

slide-120
SLIDE 120

Caller save

slide-121
SLIDE 121

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()

Code using foo Definition of foo

slide-122
SLIDE 122

Callee save

slide-123
SLIDE 123

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

slide-124
SLIDE 124

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

slide-125
SLIDE 125

This is how I’m going to call two_x_plus_y

slide-126
SLIDE 126
slide-127
SLIDE 127

Next word on stack

SP

slide-128
SLIDE 128

FP FP+1 FP+3 FP+4

Next word on stack

SP FP+2

slide-129
SLIDE 129

FP FP+1

2

FP+3 FP+4

Next word on stack

SP FP+2

slide-130
SLIDE 130

FP FP+1

2

10

FP+3 FP+4

Next word on stack

SP FP+2

slide-131
SLIDE 131

FP FP+1

2 10

FP+3 FP+4

Next word on stack

SP FP+2 two_x_plus_y receives this

slide-132
SLIDE 132
slide-133
SLIDE 133

Let’s dive into this code…

slide-134
SLIDE 134

Unused

FP

Unused

FP+1

Value of x Value of y

FP+2 FP+3 FP+4

Next word on stack

SP

Unused

What we’ve got now..

slide-135
SLIDE 135
slide-136
SLIDE 136

Return addr

FP

Caller’s FP

FP+1

Value of arg x Value of arg y

FP+3 FP+4

Next word on stack

SP

Unused

FP+2

slide-137
SLIDE 137

two_x_plus_y wants to use R1 and R2

Return addr

FP

Caller’s FP

FP+1

Value of arg x Value of arg y

FP+3 FP+4

Next word on stack

SP So make space by incrementing SP

Unused

FP+2

slide-138
SLIDE 138

Return addr

FP

Caller’s FP

FP+1

Value of arg x Value of arg y

FP+2 FP+3

Space to save R1

FP+4 INC(SP,2) SP

Space to save R2

FP+5

Next word on stack

Unused

FP+6

slide-139
SLIDE 139

Return addr

FP

Caller’s FP

FP+1

Value of arg x Value of arg y

FP+2 FP+3

Previous R1

FP+4 SP

Previous R2

FP+5

Next word on stack

Unused

FP+6

slide-140
SLIDE 140
slide-141
SLIDE 141

Return addr

FP

Caller’s FP

FP+1

Value of arg x Value of arg y

FP+2 FP+3

Previous R1

FP+4 SP

Previous R2

FP+5

Next word on stack

R1 x R2 y

Unused

FP+6

slide-142
SLIDE 142
slide-143
SLIDE 143
slide-144
SLIDE 144

Return addr

FP

Caller’s FP

FP+1

Return value (ans)

Value of arg y

FP+2 FP+3

Space to save R1

FP+4 FP+6

Space to save R2

FP+5

Next word on stack

R1 ans R2 y

Unused

SP

slide-145
SLIDE 145
slide-146
SLIDE 146

Return addr

FP

Caller’s FP

FP+1

Return value (ans)

Value of arg y

FP+2 FP+3

Space to save R1

FP+4 FP+6

Space to save R2

FP+5

Next word on stack

R1 FP+5 R2 FP+6

Unused

SP

slide-147
SLIDE 147
slide-148
SLIDE 148
slide-149
SLIDE 149

Return addr

FP

Caller’s FP

FP+1

Return value (ans)

Value of arg y

FP+2 FP+3 FP+4

Next word on stack

R1 FP+5 R2 FP+6

Unused

SP

slide-150
SLIDE 150
slide-151
SLIDE 151

Return addr

FP

Caller’s FP

FP+1

Return value (ans)

Value of arg y

FP+2 FP+3 FP+4

Next word on stack Unused

SP Now caller clears these by decrementing SP

slide-152
SLIDE 152

So which one should you use?

slide-153
SLIDE 153

You could mix and match

slide-154
SLIDE 154

Much better to pick one and stick to it

slide-155
SLIDE 155

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

slide-156
SLIDE 156

The ABI defines your calling convention

slide-157
SLIDE 157

Application Binary Interface

slide-158
SLIDE 158

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

slide-159
SLIDE 159

For example, mixing C and C++

slide-160
SLIDE 160

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