You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/part1/assembly.md
+119-2Lines changed: 119 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@
3
3
Alright, now that we know what the tools *do*, let's see what language RGBASM speaks.
4
4
I will take a short slice of the beginning of `hello-world.asm`, so that we agree on the line numbers, and you can get some syntax highlighting even if your editor doesn't support it.
@@ -41,7 +41,7 @@ For example, take line {{#line_no_of "^\s*ld a, 0" ../assets/hello-world.asm:bas
41
41
If you look further in the file, line {{#line_no_of "^\s*ld a, b" ../assets/hello-world.asm}} has `ld a, b`, which causes the value in register `b` to be copied into register `a`.
@@ -57,6 +57,111 @@ The descriptions there are more succinct, since they're intended as reminders, n
57
57
58
58
:::
59
59
60
+
## Directives
61
+
62
+
In a way, instructions are destined to the console's CPU, and comments are destined to the programmer.
63
+
But some lines are neither, and are instead sort of metadata destined to RGBDS itself.
64
+
Those are called *directives*, and our Hello World actually contains three of those.
65
+
66
+
### Including other files
67
+
68
+
```rgbasm,linenos
69
+
{{#include ../assets/hello-world.asm:4}}
70
+
```
71
+
72
+
Line 1 *includes*`hardware.inc`[^hw_inc_directives].
73
+
Including a file has the same effect as if you copy-pasted it, but without having to actually do that.
74
+
75
+
It allows sharing code across files easily: for example, if two files `a.asm` and `b.asm` were to include `hardware.inc`, you would only need to modify `hardware.inc` once for the modifications to apply to both `a.asm` and `b.asm`.
76
+
If you instead copy-pasted the contents manually, you would have to edit both copies in `a.asm` and `b.asm` to apply the changes, which is more tedious and error-prone.
77
+
78
+
`hardware.inc` defines a bunch of constants related to interfacing with the hardware.
79
+
Constants are basically names with a value attached, so when you write out their name, they are replaced with their value.
80
+
This is useful because, for example, it is easier to remember the address of the **LCD****C**ontrol register as `rLCDC` than `$FF40`.
81
+
82
+
We will discuss constants in more detail in Part Ⅱ.
83
+
84
+
### Sections
85
+
86
+
Let's first explain what a "section" is, then we will see what line 3 does.
87
+
88
+
A section represents a contiguous range of memory, and by default, ends up *somewhere* not known in advance.
89
+
If you want to see where all the sections end up, you can ask RGBLINK to generate a "map file" with the `-m` flag:
90
+
91
+
```console
92
+
$ rgblink hello-world.o -m hello-world.map
93
+
```
94
+
95
+
...and we can see, for example, where the `"Tilemap"` section ended up:
96
+
97
+
```
98
+
SECTION: $05a6-$07e5 ($0240 bytes) ["Tilemap"]
99
+
```
100
+
101
+
Sections cannot be split by RGBDS, which is useful e.g. for code, since the processor executes instructions one right after the other (except jumps, as we will see later).
102
+
There is a balance to be struck between too many and not enough sections, but it typically doesn't matter much until banking is introduced into the picture—and it won't be until much, much later.
103
+
104
+
So, for now, let's just assume that one section should contain things that "go together" topically, and let's examine one of ours.
105
+
106
+
```rgbasm,linenos,start=3
107
+
{{#include ../assets/hello-world.asm:6}}
108
+
```
109
+
110
+
So!
111
+
What's happening here?
112
+
Well, we are simply declaring a new section; all instructions and data after this line and until the next `SECTION` one will be placed in this newly-created section.
113
+
Before the first `SECTION` directive, there is no "active" section, and thus generating code or data will be met with a `Cannot output data outside of a SECTION` error.
114
+
115
+
The new section's name is "`Header`".
116
+
Section names can contain any characters (and even be empty, if you want), and must be unique[^sect_name].
117
+
The `ROM0` keyword indicates which "memory type" the section belongs to ([here is a list](https://rgbds.gbdev.io/docs/v0.5.2/rgbasm.5#SECTIONS)).
118
+
We will discuss them in Part Ⅱ.
119
+
120
+
The `[$100]` part is more interesting, in that it is unique to this section.
121
+
See, I said above that:
122
+
123
+
> a section \[...\] by default, ends up *somewhere* not known in advance.
124
+
125
+
However, some memory locations are special, and so sometimes we need a specific section to span a specific range of memory.
126
+
To enable this, RGBASM provides the `[addr]` syntax, which *forces* the section's starting address to be `addr`.
127
+
128
+
In this case, the memory range $100–$14F is special, as it is the *ROM's header*.
129
+
We will discuss the header in a couple lessons, but for now, just know that we need not to put any of our code or data in that space.
130
+
How do we do that?
131
+
Well, first, we begin a section at address $100, and then we need to reserve some space.
132
+
133
+
### Reserving space
134
+
135
+
```rgbasm,linenos,start=5
136
+
{{#include ../assets/hello-world.asm:8:10}}
137
+
```
138
+
139
+
Line 7 claims to "Make room for the header", which I briefly mentioned just above.
140
+
For now, let's focus on what `ds` actually does.
141
+
142
+
`ds` is used for *statically* allocating memory.
143
+
It simply reserves some amount of bytes, which are set to a given value.
144
+
The first argument to `ds`, here `$150 - @`, is *how many bytes to reserve*.
145
+
The second (optional) argument, here `0`, is *what value to set each reserved byte to*[^ds_pattern].
146
+
147
+
We will see why these bytes must be reserved in a couple of lessons.
148
+
149
+
It is worth mentioning that this first argument here is an *expression*.
This expression is a simple subtraction: $150 minus `@`, which is a special symbol that stands for "the current memory address".
152
+
153
+
::: tip
154
+
155
+
A symbol is essentially "a name attached to a value", usually a number.
156
+
We will explore the different types of symbols throughout the tutorial, starting with labels in the next section.
157
+
158
+
A numerical symbol used in an expression evaluates to its value, which must be known when compiling the ROM—in particular, it can't depend on any register's contents.
159
+
160
+
:::
161
+
162
+
Oh, but you may be wondering what the "memory addresses" I keep mentioning are.
163
+
Let's see about those!
164
+
60
165
---
61
166
62
167
[^instr_directive]:
@@ -65,3 +170,15 @@ Technically, instructions in RGBASM are implemented as directives, basically wri
65
170
[^ld_imm_from]:
66
171
The curious reader may ask where the value is copied *from*. The answer is simply that the \"immediate\" byte ($00 in this example) is stored in ROM just after the instruction's opcode byte, and it's what gets copied to `a`.
67
172
We will come back to this when we talk about how instructions are encoded later on.
173
+
174
+
[^hw_inc_directives]:
175
+
`hardware.inc` itself contains more directives, in particular to define a lot of symbols.
176
+
They will be touched upon much later, so we won't look into `hardware.inc` yet.
177
+
178
+
[^sect_name]:
179
+
Section names actually only need to be unique for "plain" sections, and function differently with "unionized" and "fragment" sections, which we will discuss much later.
180
+
181
+
[^ds_pattern]:
182
+
Actually, since RGBASM 0.5.0, `ds` can accept a *list* of bytes, and will repeat the pattern for as many bytes as specified.
183
+
It just complicates the explanation slightly, so I omitted it for now.
184
+
Also, if the argument is omitted, it defaults to what is specified using the `-p` option **to RGBASM**.
0 commit comments