Skip to content

Commit 3ab052f

Browse files
update docs some more
Signed-off-by: mateoconlechuga <matthewwaltzis@gmail.com>
1 parent 82079fb commit 3ab052f

File tree

2 files changed

+51
-47
lines changed

2 files changed

+51
-47
lines changed

docs/local-build.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ fi
88

99
source venv/bin/activate
1010

11-
export default_version='v10.0'
12-
export versions='v10.0 v9.2 v9.1 v9.0 nightly'
11+
export default_version=`git describe --abbrev=6 --dirty --always`
12+
export versions="$default_version v9.2 v9.1 v9.0 nightly"
1313
export current_version=$default_version
1414

1515
sphinx-build -b html . build/html

docs/static/asm.rst

Lines changed: 49 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ Assembly
66
Assembly routines can be linked into a C/C++ program by putting them into the same **src** directory that your C/C++ sources are in, but with an **.asm** extension.
77
These can be placed in any subdirectory of **src** just like C/C++ sources.
88

9+
Assembly Files
10+
--------------
11+
912
.. _asm-consts:
1013

1114
Constants
12-
---------
15+
^^^^^^^^^
1316

1417
The top of the file is a good place defining constants or including other files that define constants.
1518
These will be availabe throughout the rest of the file, but not in other files.
@@ -22,42 +25,42 @@ See :ref:`asm-section` to fix this problem.
2225
.. _asm-assume:
2326

2427
Assume
25-
------
28+
^^^^^^
2629

2730
You should add a :code:`assume adl=1` before trying to emit any code, which ensures that you get 24-bit eZ80 instructions.
28-
If you end a assembly file in :code:`assume adl=0` which is the eZ80's 16-bit Z80 compatibility mode, it will propogate to another random assembly file.
29-
All toolchain and compiler-generated sources make sure to reset the mode at the top of the file and end the file in the same mode, but if one of your sources end in Z80 mode, then any other one of your sources might begin in Z80 mode, so it is safer to put it in every file.
31+
If you end an assembly file with :code:`assume adl=0` (which is the eZ80's 16-bit Z80 compatibility mode), it will propogate to another random assembly file.
32+
All toolchain and compiler-generated sources make sure to reset the mode at the top of the file and end the file in the same mode, but if one of your sources end in Z80 mode, then any other one of your sources might begin in Z80 mode, so it is safer to put the :code:`assume` line in every file.
3033

3134
.. _asm-section:
3235

3336
Section
34-
-------
37+
^^^^^^^
3538

3639
Now that we are in the correct mode, we need to tell the linker where to put things.
3740
We use :code:`section .text` for code, :code:`section .data` for variables, and :code:`section .rodata` for constant data.
3841
Currently these are all placed in RAM, so which section you choose to switch to is much less important than how often you switch sections, even if you are switching to the same section you are already in.
3942
This is because every time you start a new, or restart the same, section, the linker gets a new opportunity to delete a block of dead code/data.
4043
Because of this, the correct time to switch sections is usually every time you start a new function or variable.
41-
You should not let execution fall off the end of a block because you won't know if that block will be included or deleted from the output, however you can if you say `require _symbol` of some public or private symbol defined in the next section to ensure that if the current block is included, then that will force the next block to also be included.
44+
You should not let execution fall off the end of a block because you won't know if that block will be included or deleted from the output, however you can if you say :code:`require _symbol` of some public or private symbol defined in the next section to ensure that if the current block is included, then that will force the next block to also be included.
4245
To define a symbol in a block that can be referenced from other blocks, you should do :code:`private _symbol` or :code:`public _symbol` right before its definition.
43-
If it is private then it is only able to be referenced from the same file and no :ref:`asm-extern` should be used.
44-
If it is public then it can be referenced within the same file without :ref:`asm-extern` just like private symbols, but public symbols can also be referenced from other files and even C/C++!
46+
If it is private then it is only able to be referenced from the same file and no :ref:`extern <asm-extern>` should be used.
47+
If it is public then it can be referenced within the same file without :ref:`extern <asm-extern>` just like private symbols, but public symbols can also be referenced from other files and even C/C++!
4548
The public assembly symbol named :code:`_symbol` is accessible in C by the global name :code:`symbol`, assuming it is properly declared, with your asm symbol acting as the definition.
4649

4750
.. _asm-extern:
4851

4952
Extern
50-
------
53+
^^^^^^
5154

5255
At the end of the file is a good place to list every external symbol that you might depend on like :code:`extern _symbol`.
5356
This includes both public symbols defined in another assembly file and global symbols from C, prefixed with an underscore like usual.
5457
Lastly, you should not let execution fall off the end of a file because the next file that gets assembled is unpredictable and you could end up anywhere!
5558
Block ordering can only be relied on within a single file, and only for blocks belonging to the same section.
5659

57-
Meanwhile, back in C
58-
--------------------
60+
Linking ASM routines to C/C++
61+
-----------------------------
5962

60-
On the C/C++ side of things, a separate header file should define a extern C global prototype for the function if it is to be called from C/C++ code.
63+
If an assembly function needs to be called from C, a separate header file should define a extern C global prototype.
6164
In C this looks like a normal function or global declaration, and in C++ it's the same thing but in an :code:`extern "C" {}` block.
6265

6366
Below is an example C prototype followed by the assembly implementation:
@@ -108,57 +111,58 @@ Below is an example C prototype followed by the assembly implementation:
108111
}
109112
110113
Arguments
111-
---------
114+
^^^^^^^^^
112115

113116
Arguments are pushed from last to first corresponding to the C prototype.
114117
In eZ80, 3 bytes are always pushed to the stack regardless of the actual size.
115118
However, the assembly function must be careful to only use the valid bytes that are pushed.
116119
For example, if a *short* type is used, the upper byte of the value pushed on the stack will contain arbitrary data.
117120
This table lists the locations relative to *sp* from within the called funciton.
121+
Note that :code:`sp + [0,2]` contains the return address.
118122

119123
+------------+------------+----------------------+
120-
| C Type | Size | Stack Location |
124+
| C/C++ Type | Size | Stack Location |
121125
+============+============+======================+
122126
| char | 1 byte | sp + [3] |
123127
+------------+------------+----------------------+
124-
| short | 2 bytes | sp + [3:4] |
128+
| short | 2 bytes | sp + [3,4] |
129+
+------------+------------+----------------------+
130+
| int | 3 bytes | sp + [3,5] |
125131
+------------+------------+----------------------+
126-
| int | 3 bytes | sp + [3:5] |
132+
| long | 4 bytes | sp + [3,6] |
127133
+------------+------------+----------------------+
128-
| long | 4 bytes | sp + [6]: sp + [3:5] |
134+
| long long | 8 bytes | sp + [3,10] |
129135
+------------+------------+----------------------+
130-
| float | 4 bytes | sp + [6]: sp + [3:5] |
136+
| float | 4 bytes | sp + [3,6] |
131137
+------------+------------+----------------------+
132-
| double | 4 bytes | sp + [6]: sp + [3:5] |
138+
| double | 4 bytes | sp + [3,6] |
133139
+------------+------------+----------------------+
134-
| pointer | 3 bytes | sp + [3:5] |
140+
| pointer | 3 bytes | sp + [3,5] |
135141
+------------+------------+----------------------+
136142

137143
Returns
138-
-------
144+
^^^^^^^
139145

140-
This table lists which registers are used for return values.
146+
This table lists which registers are used for return values from a function.
141147
The type's sign does not affect the registers used, but may affect the value returned.
142-
143-
.. note::
144-
145-
| **xx**: Byte must contain valid data.
146-
| **??**: Byte contents don't matter.
147-
148-
+------------+------------+-------------------+
149-
| C Type | Register | Register Contents |
150-
+============+============+===================+
151-
| char | A | xx |
152-
+------------+------------+-------------------+
153-
| short | HL | ?? xx xx |
154-
+------------+------------+-------------------+
155-
| int | HL | xx xx xx |
156-
+------------+------------+-------------------+
157-
| long | E:HL | xx: xx xx xx |
158-
+------------+------------+-------------------+
159-
| float | E:HL | xx: xx xx xx |
160-
+------------+------------+-------------------+
161-
| double | E:HL | xx: xx xx xx |
162-
+------------+------------+-------------------+
163-
| pointer | HL | xx xx xx |
164-
+------------+------------+-------------------+
148+
The LSB is located in the register on the far right of the expression, e.g. ``E:HL`` indicates register ``L`` stores the LSB.
149+
150+
+------------+-------------------+
151+
| C/C++ Type | Return Register |
152+
+============+===================+
153+
| char | A |
154+
+------------+-------------------+
155+
| short | HL |
156+
+------------+-------------------+
157+
| int | UHL |
158+
+------------+-------------------+
159+
| long | E:UHL |
160+
+------------+-------------------+
161+
| long long | BC:UDE:UHL |
162+
+------------+-------------------+
163+
| float | E:UHL |
164+
+------------+-------------------+
165+
| double | E:UHL |
166+
+------------+-------------------+
167+
| pointer | UHL |
168+
+------------+-------------------+

0 commit comments

Comments
 (0)