-
Notifications
You must be signed in to change notification settings - Fork 2
/
review.txt
138 lines (112 loc) · 7.54 KB
/
review.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
Review
Know the Concepts
• What are primitives?
Primitives are the lowest level of building blocks provided by a language.
They provide instructions to the CPU on how to perform certain actions such as mov, add, etc.
Some examples of primitives in assembly are mov, add, jle, cmp, etc.
• What are calling conventions?
Calling conventions are standards used by programming languages that describe how a program
will transfer parameter values, how functions will return data, how variables will be passed in the program, etc.
These conventions vary from language to language.
• What is the stack?
The stack refers to a section in memory that is reserved for function calls and local variables.
As data is pushed onto the top of the stack, the %esp (extended stack pointer) register will hold a pointer
to the new location, i.e. the top.
Even though a piece of data is reffered to as "the top of the stack", it actually is located LOWER in memory.
The more items added to the stack, the closer the "top" gets to the bottom of the allocated memory addresses.
• How do pushl and popl affect the stack? What special-purpose register do
they affect?
pushl (push long) will move data onto the top of the stack.
popl (pop long) will remove data from the top of the stack.
The data that is moved onto or removed from the stack depends on the
pointer stored in the %esp special-purpose register.
As data is pushed onto the top of the stack, the %esp pointer is decremented by four bytes,
pointing to the new top.
The opposite is true as data is removed from the top of the stack.
In the case of popl, the %esp pointer will increment by four bytes.
• What are local variables and what are they used for?
Local variables are processed within a functions lifespan.
They do not exist outside of the function they were defined in,
meaning that another function or another part of the program can not use the variable.
Localizing variables is important for code organization,
it allows for data to be encapsulated entirely within the functions that need them and nowhere else.
Other than code organization, local variables also improve memory management by freeing up memory once a function expires.
• Why are local variables so necessary in recursive functions?
Everytime a function is called, most of the registers will be wiped.
In order to preserve data between functions we need to move the values of any
necessary register onto the stack.
The %eax is one of the only registers to survive, this is why it used for return values.
• What are %ebp and %esp used for?
The %ebp (extended base pointer) register is a special purpose register that is used to establish a
base for referencing local variables, parameters, and other items within a stack frame.
The base pointer is typically used as a stable reference point.
The %esp (extended stack pointer) register is a special purpose register that is used to keep track of the top of a stack.
When using PUSHL to push items onto the stack the %esp register is decremented to point to the new top,
in this way %esp helps with stack management.
• What is a stack frame?
A stack frame is a reserved section of memory that contains a functions parameters,
local variables, return address, etc.
Use the Concepts
• Write a function called square which receives one argument and returns the
square of that argument.
Refer to square.s program for solution.
• Write a program to test your square function.
Refer to square.s program for solution.
• Convert the maximum program given in the Section called Finding a Maximum
Value in Chapter 3 so that it is a function which takes a pointer to several values
and returns their maximum. Write a program that calls maximum with 3
different lists, and returns the result of the last one as the program’s exit status
code.
Refer to maximum.s for solution.
• Explain the problems that would arise without a standard calling convention.
Calling conventions describe the way that functions and code should interact with each other.
They're an agreement between caller and callee, where the callee is a function and the
caller is the code that calls the function.
The callee may use the arguments passed to it by the caller, operate on them and return a value but
it should follow a certain standard when doing so.
The same goes for the callee, it must be responsible for the way it sends and receives the arguments/return values.
If there was no agreed upon convention between the two, data would not be useful since there is no guarantee that
the caller and callee are making proper use of the values they are manipulating.
For example, a function that takes two arguments, a and b, and subtracts b from a would return the number 2 if
a was 5 and b was 3.
But if the callee follows no standard calling convention he might receive the number -2 if he passed in the values in a reverse order.
Without calling conventions, results would be disordered.
Going Further
• Do you think it’s better for a system to have a large set of primitives or a small
one, assuming that the larger set can be written in terms of the smaller one?
If the larger set of primitives can be made up of the smaller primitives, that already exist in the system,
it would be redundant.
Larger sets of primitives may improve the overall user experience but it comes with drawbacks,
such as software bloat.
• The factorial function can be written non-recursively. Do so.
Refer to factorial-non-recursive.s for solution.
• Find an application on the computer you use regularly. Try to locate a specific
feature, and practice breaking that feature out into functions. Define the
function interfaces between that feature and the rest of the program.
In a regular text editor such as Notepad you have the ability to delete a character from the text in the editor.
This feature might have a function called Delete_Character, maybe it takes a cursor position to determine the character before that
needs to be deleted. Maybe there's a call to update the UI through another function.
There might be a function that takes keypress and determines what course of action to take based on what key is passed as input.
If the backspace key is pressed the Delete_Character function will be called.
The Delete_Character function might take a portion of text and a position as input and return the updated text.
• Come up with your own calling convention. Rewrite the programs in this
chapter using it. An example of a different calling convention would be to pass
paramters in registers rather than the stack, to pass them in a different order, to
return values in other registers or memory locations. Whatever you pick, be
consistent and apply it throughout the whole program.
Skipped.
• Can you build a calling convention without using the stack? What limitations
might it have?
A calling convention CAN be created that does not use the stack however,
as programs become increasingly complex they will reach a point where registers alone are not sufficient.
Any convention that ignores the stack, or memory in general, will need to be simple enough to store all values
in registers.
• What test cases should we use in our example program to check to see if it is
working properly?
1. Boundary Test Cases
2. Normal Test Cases
3. Invalid Input Test Cases
4. Edge Cases
5. Stress Test Cases
6. Corner Cases
7. Error Handling Test Cases