Which ARM instruction set are you working with, based on your code snippets it is either ARM (armv7 or older). ARM or thumb instructions
int32_t Add(int32_t a, int32_t b)
{
return a + b ;
}
I will let you try godbolt or a command line compiler, etc. The teacher has to know you have access to the internet and tools. But you had better be able to understand and defend code from the compiler otherwise it is just plagiarism and it will become obvious.
So int32_t means 32 bits which is the size of registers. compiled languages have a "calling convention" or sometimes abi (application binary interface). Basically a set of rules for each function. The first parameter is passed this way with some exceptions for specific types. The second parameter is passed this way based in part on first and its type, and so on. the return value is handled this way.
There are instruction set things like a call to a function (look up bl) puts the return address in the link register, r14 so you typically but are not limited to using bx lr to return, it will be bx something, there are cases where it is not lr but it is the contents that were in lr.
if function a calls function b, the return to function a will be in the link register (assume that there is only one link register). if b calls function c though that changes the link register to return to function b, how do we get back to function a? You save the link register on the stack and pop it back off. Everything you add to the stack you need to remove before you return.
Does the Add function call another function? (no) That is the first test for needing to use the stack to save the link register. Does the Add function have more than a few intermediate variables in flight at any one time? That may require some of them to remain on the stack. (no)
You probably do not need to use the stack for the Add function, does not mean you cannot, you are more than welcome to.
I will tell you that the arm compilers I have used for a function like this the two parameters are passed using registers, you can figure out which ones as this is part of your assignment I will call them ra and rb.
so you need a label which is assembly language dependent (assembler, the tool, not target) so it may or may not have a colon as an example
Add:
...
bx lr
the bx lr I gave you
In the middle you need to add the two numbers
rc = ra + rb
Or perhaps
ra = ra + rb
You need to figure out the input register names, and the output register names (it is a register not the stack for the C compilers I have seen for ARM).
so it will be something along the lines of
Add:
rc = ra + rb (a + b)
rd = rc (put the result in the return register)
bx lr
And you might be able to optimize that, you have to figure out what those
instructions and registers are. And the rules for those instructions.
The subtract one should be even easier once you do the Add function.
int32_t Square2x(int32_t x)
{
return Square(x + x) ;
}
Is it calling a function, yes, so what does that mean with respect to preserving the return address? That should define your skeleton or frame of your function.
You need to deal with x + x before calling the function. As you would expect
the calling convention has a specific register that x will show up in every time
for a 32 bit parameter like this. And that is the same register used to call Square2X as well as Square as well as Less1 and Last and one of the two operands to Add. So if I call that register rx, then before calling Square you need to
compute rx = rx + rx yes? Or there is another way that gives the same result. Then you call Square. Note you can optimize here
and save on something.
int32_t Last(int32_t x)
{
return x + SquareRoot(x) ;
}
You are calling a function, that triggers some code. You are passing x that came
in to the function called, probably does not need to be moved or modified. But I will tell you that that specific register based on the conventions I know about
can be modified by the called function. So when SquareRoot returns that x register might not contain x anymore. So before calling SquareRoot how can you preserve it for later, so you can add it to the result that comes back from SquareRoot?
From Add and Less1 you should already know the passed in register for a single 32-bit parameter like this as well as the return register for a result like this, let's assume that SquareRoot is passed and returns an int32_t otherwise this gets a whole lot harder. All functions use the same rules so you know what register x is passed to SquareRoot and you know what register it comes back in. So you need to figure out how to preserve the x passed to Last so you can add it later. You are already preserving another register that gets messed up and you need to save later. But you will see compilers might have a twist as to how they do this to avoid an extra instruction or two. Depending on the ARM instruction set this one should be 5.
Add you are looking for two instructions.
Less1, two instructions
Square2X first pass four instructions. I think you can make this two.
Last, five instructions
Depending on the instruction set and architecture version there might be more for some of these.