mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-25 00:16:44 +08:00
better looking plus edits
This commit is contained in:
parent
bd1fe10183
commit
5c6fde83a1
2 changed files with 143 additions and 129 deletions
|
|
@ -4,7 +4,10 @@ Calling functions, passing parameters to them and receiving back return
|
|||
values is basic to using `C` and and `C++`. Calling methods (which are
|
||||
functions connected to objects) is similar but with enough differences
|
||||
to warrant its own discussion to be provided later in the chapter on
|
||||
[structs](../struct/structs.md).
|
||||
[structs](../structs/using.md).
|
||||
|
||||
Be sure to read [this](./README2.md) for information about
|
||||
passing parameters to functions.
|
||||
|
||||
## Bottom Line Concept
|
||||
|
||||
|
|
@ -62,8 +65,9 @@ allows the function to `ret`urn.
|
|||
## **bl**
|
||||
|
||||
Branch-with-link computes the address of the instruction following it.
|
||||
It places this address into `x30` and then branches to the label
|
||||
provided. It makes one link of breadcrumbs to follow to get back
|
||||
|
||||
It places this address into register `x30` and then branches to the
|
||||
label provided. It makes one link of breadcrumbs to follow to get back
|
||||
following a `ret`.
|
||||
|
||||
**This is why it is absolutely essential to backup `x30` inside your
|
||||
|
|
@ -88,7 +92,7 @@ hw: .asciz "Hello World!" // 10
|
|||
|
||||
What could possibly go wrong?
|
||||
|
||||
Here is a listing from `gdb` since running the program simply
|
||||
Here is a listing from `gdb` since running the program
|
||||
hangs:
|
||||
|
||||
```text
|
||||
|
|
@ -128,7 +132,9 @@ return.
|
|||
So, when line 7 executes it puts the contents of `x30` into the
|
||||
program counter and branches to it.
|
||||
|
||||
And the problem with this is? Hint: notice where `gdb` put us after
|
||||
And the problem with this is?
|
||||
|
||||
Hint: notice where `gdb` put us after
|
||||
the control-C. Still on line 7. An infinite loop of returning to the
|
||||
return statement.
|
||||
|
||||
|
|
@ -152,7 +158,7 @@ hw: .asciz "Hello World!" // 12
|
|||
```
|
||||
|
||||
The address to which `main()` should return is pushed onto the stack on
|
||||
line 5. It is safe there.
|
||||
line 5. It should be safe there.
|
||||
|
||||
It is recovered from the stack on line 8 and used by line 9's `ret`.
|
||||
|
||||
|
|
@ -161,14 +167,16 @@ It is recovered from the stack on line 8 and used by line 9's `ret`.
|
|||
First, let's take a trip back in time to the early days of C.
|
||||
|
||||
[Stephen Bourne](https://en.wikipedia.org/wiki/Stephen_R._Bourne) was
|
||||
writing `sh` the first shell for Unix. He noticed that every function
|
||||
writing `sh`, the first shell for Unix. He noticed that every function
|
||||
had to return a value - even functions that had no reason to return
|
||||
a value. In these early days, `void` functions did not yet exist.
|
||||
a value.
|
||||
|
||||
Bourne argued that an instruction could be saved if the concept of
|
||||
`void` functions were added to C. Saving one instruction per function
|
||||
was really valuable - so that's how we get `void` functions that
|
||||
return no value.
|
||||
In these early days, `void` functions did not yet exist.
|
||||
|
||||
Bourne argued that an instruction could be saved per function if the
|
||||
concept of `void` functions were added to C. Saving one instruction per
|
||||
function was really valuable - so that's how we get `void` functions
|
||||
that return no value.
|
||||
|
||||
What about functions that do return a value?
|
||||
|
||||
|
|
@ -179,7 +187,7 @@ Note that `x0` and `x1` could also be `w0` and `w1` or even the first
|
|||
and second floating point registers if the function is returning a
|
||||
`float` or `double`.
|
||||
|
||||
Here are samples, first in C++ then in the corresponding assembly
|
||||
Here are samples, first in C / C++ then in the corresponding assembly
|
||||
language:
|
||||
|
||||
```c++
|
||||
|
|
@ -223,3 +231,8 @@ ReturnsADouble: // 13
|
|||
|
||||
Note, the use of the floating point move instruction as well as the
|
||||
single precision and double precision registers.
|
||||
|
||||
## Repeating the TL;DR
|
||||
|
||||
If your functions call *any* other functions, `x30` must be backed
|
||||
up on the stack and then restored into `x30` before returning.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ For the purposes of the present discussion, we assume all parameters are `long i
|
|||
|
||||
Up to 8 parameters are passed in the scratch registers (of which there are 8). These are `x0` through `x7`. *Scratch* means the value of the register can be changed at will without any need to backup or restore their values.
|
||||
|
||||
**This also means that you cannot count on the contents of the scratch registers maintaining their value if your function makes any function calls itself.**
|
||||
**This means that you cannot count on the contents of the scratch registers maintaining their value if your function makes any function calls.**
|
||||
|
||||
For example:
|
||||
|
||||
|
|
@ -150,9 +150,10 @@ Here is a sample function that requires 9 parameters (for who knows what reason)
|
|||
```c++
|
||||
#include <stdio.h>
|
||||
|
||||
void SillyFunction(long p1, long p2, long p3, long p4, long p5, long p6,
|
||||
long p7, long p8, long p9) {
|
||||
printf("This example hurts my brain: %ld %ld\n", p8, p9);
|
||||
void SillyFunction(long p1, long p2, long p3, long p4,
|
||||
long p5, long p6, long p7, long p8,
|
||||
long p9) {
|
||||
printf("This example hurts: %ld %ld\n", p8, p9);
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
|
@ -198,9 +199,9 @@ main: // 13
|
|||
ret // 27
|
||||
// 28
|
||||
.data // 29
|
||||
fmt: .asciz "This example hurts my brain: %ld %ld\n" // 30
|
||||
fmt: .asciz "This example hurts: %ld %ld\n" // 30
|
||||
// 31
|
||||
.end
|
||||
|
||||
```
|
||||
|
||||
Notice how `main()` puts the first 8 parameters into the scratch registers `x0` through `x7` using `Lines 17` to `24`. But first, it put the ninth parameter on the stack. It did the stack parameter first so that the stack pointer could be manipulated in a scratch register.
|
||||
|
|
|
|||
Loading…
Reference in a new issue