# 汇编代写 | CSC-421/621 Homework 2

CSC-421/621 Homework 2:
Structured programming
Problem 1:
The assembly language we used in Homework 1 technically has enough features to program any algorithm
that operates on integers, but not necessarily conveniently. One feature it lacks is the ability to define
functions. In all high-level programming languages, code can be put into reusable functions, which can be
called with different parameters from different places in the program.
To make functions possible in our language, we’ll add two new instructions:
CALL label
Conceptually, call the function. Specifically: Jump to label, and push the address of this call site onto
the call stack.
RET
Conceptually, return from the function. Specifically: Jump to the instruction immediately after the
last call site that was saved on the call stack, and then pop (remove) that address from the call stack.
Consider this program, which defines a function multiply and then computes 2*3*4 by calling multiply
twice.
JMP start
multiply:
LOAD 0,R3
LOAD -1,R4
loop:
ADD R1,R3
ADD R4,R2
JGZ R2,loop
MOV R3,R1
RET
start:
LOAD 2,R1
LOAD 3,R2
CALL multiply
LOAD 4,R2
CALL multiply
(a): Why did we need CALL? Couldn’t we just JMP to multiply each time we wanted to use it?
(b): Function calling at the assembly level only works if there is a calling convention where the caller and
callee agree on where parameters will be passed, and where results will be stored. From looking at the
example above, what can you infer about the calling convention? Explain the (apparent) rules for how
functions receive their parameters and return their values.
(c): Can you think of any problems or limitations of the calling convention that this code seems to be
using?
(d): Draw the call stack as it would look during the execution of the first multiply call (i.e. after the first
CALL, but before the first RET). Treat start as a function with zero parameters called at the start of the
program, for the purposes of drawing the call stack (even though it isn’t called with CALL).
(e): Draw the call tree showing all function invocations that would happen during the execution of this
program. A call tree should have one box (called the activation record) for each time a function was called,
along with arrows showing who called who. Again, treat start as a function with zero parameters for this
purpose.
Extra credit: This implementation of multiply isn’t quite correct, although it works fine for computing
2*3*4. That doesn’t change what the calling convention or call stack looks like. But for extra credit,
explain what’s wrong with it, and provide a correct version that works for all integers.
Problem 2:
Some languages (such as Python) distinguish statements from expressions. An expression evaluates to a
value, and therefore can appear in contexts that expect values, called an expression context. Statements can
have effects and can call functions, but don’t themselves evaluate to anything, and therefore it’s not legal to
treat them as values and use them in expression contexts.
Python originally had only conditional statements, not conditional expressions. Python 2.5 (released in
2006) added a new syntax for conditional expressions, which is sometimes more convenient, although (as
we will see below), it doesn’t always make code more readable. The full proposal is PEP 308 (PEP stands
for “Python Enhancement Proposal”); a short summary of the feature can be read in the Python 2.5 release
notes (https://docs.python.org/2.5/whatsnew/pep-308.html).
Each of the following program snippets uses the new conditional expression feature. How would you write
them if that feature hadn’t been added? For each one, write equivalent code that uses conditional statements
instead:
(a): x = a/b if b != 0 else 0
(b): result = pow(x, y if y > 0 else 0)
(c): state = “ice” if temp <= 32 else "water" if temp <= 100 else "vapor" (d): truncatedPower = pow(x, y if abs(y) <= 10 else 10 * (-1 if y < 0 else 1)) Problem 3: Python has a number of different iteration constructs. Consider this set of nested for loops that prints all fractions where the numerator and denominator are between 1 and 99 inclusive (ignoring any fancy features like reducing them to lowest terms): for x in range(1,100): for y in range(1,100): print(str(x) + "/" + str(y)) (a): Rewrite this to use nested while loops instead. (b): Rewrite this to use a single while True infinite loop, with all incrementing, conditional tests, and loop exit (with break) done explicitly. In other words, your solution should look like this: # initialize some variables ... while True: # loop body ...

E-mail: vipdue@outlook.com  微信号:vipdue