mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Rewrite and rearrange some rgbasm docs
This commit is contained in:
532
man/rgbasm.5
532
man/rgbasm.5
@@ -175,11 +175,8 @@ or
|
|||||||
If specified, prints this character in front of non-negative numbers.
|
If specified, prints this character in front of non-negative numbers.
|
||||||
.It Ql <prefix> Ta May be
|
.It Ql <prefix> Ta May be
|
||||||
.Ql # .
|
.Ql # .
|
||||||
If specified, prints the appropriate prefix for numbers,
|
If specified, prints a base prefix for non-decimal integer types
|
||||||
.Ql $ ,
|
.Pq So $ Sc , So & Sc , or So % Sc .
|
||||||
.Ql & ,
|
|
||||||
or
|
|
||||||
.Ql % .
|
|
||||||
.It Ql <align> Ta May be
|
.It Ql <align> Ta May be
|
||||||
.Ql - .
|
.Ql - .
|
||||||
If specified, aligns left instead of right.
|
If specified, aligns left instead of right.
|
||||||
@@ -197,7 +194,7 @@ followed by one or more
|
|||||||
.Ql 0
|
.Ql 0
|
||||||
\[en]
|
\[en]
|
||||||
.Ql 9 .
|
.Ql 9 .
|
||||||
If specified, prints this many digits of a fixed-point fraction.
|
If specified, prints this many fractional digits of a fixed-point number.
|
||||||
Defaults to 5 digits, maximum 255 digits.
|
Defaults to 5 digits, maximum 255 digits.
|
||||||
.It Ql <type> Ta Specifies the type of value.
|
.It Ql <type> Ta Specifies the type of value.
|
||||||
.El
|
.El
|
||||||
@@ -205,8 +202,8 @@ Defaults to 5 digits, maximum 255 digits.
|
|||||||
All the format specifier parts are optional except the
|
All the format specifier parts are optional except the
|
||||||
.Ql <type> .
|
.Ql <type> .
|
||||||
Valid print types are:
|
Valid print types are:
|
||||||
.Bl -column -offset indent "Print type" "Lowercase hexadecimal" "Example"
|
.Bl -column -offset indent "Type" "Lowercase hexadecimal" "Example"
|
||||||
.It Sy Print type Ta Sy Format Ta Sy Example
|
.It Sy Type Ta Sy Format Ta Sy Example
|
||||||
.It Ql d Ta Signed decimal Ta -42
|
.It Ql d Ta Signed decimal Ta -42
|
||||||
.It Ql u Ta Unsigned decimal Ta 42
|
.It Ql u Ta Unsigned decimal Ta 42
|
||||||
.It Ql x Ta Lowercase hexadecimal Ta 2a
|
.It Ql x Ta Lowercase hexadecimal Ta 2a
|
||||||
@@ -214,7 +211,7 @@ Valid print types are:
|
|||||||
.It Ql b Ta Binary Ta 101010
|
.It Ql b Ta Binary Ta 101010
|
||||||
.It Ql o Ta Octal Ta 52
|
.It Ql o Ta Octal Ta 52
|
||||||
.It Ql f Ta Fixed-point Ta 1234.56789
|
.It Ql f Ta Fixed-point Ta 1234.56789
|
||||||
.It Ql s Ta String Ta \&"example\&"
|
.It Ql s Ta String Ta string contents
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Examples:
|
Examples:
|
||||||
@@ -515,21 +512,17 @@ is special in that it causes the character following it to be
|
|||||||
.Dq escaped ,
|
.Dq escaped ,
|
||||||
meaning that it is treated differently from normal.
|
meaning that it is treated differently from normal.
|
||||||
There are a number of escape sequences you can use within a string:
|
There are a number of escape sequences you can use within a string:
|
||||||
.Bl -column -offset indent "Qo \e1 Qc \[en] Qo \e9 Qc"
|
.Bl -column -offset indent "Sequence"
|
||||||
.It Sy String Ta Sy Meaning
|
.It Sy Sequence Ta Sy Meaning
|
||||||
.It Ql \e\e Ta Produces a backslash
|
.It Ql \e\e Ta Backslash Pq escapes the escape character itself
|
||||||
.It Ql \e" Ta Produces a double quote without terminating
|
.It Ql \e" Ta Double quote Pq does not terminate the string
|
||||||
.It Ql \e{ Ta Curly bracket left
|
.It Ql \e{ Ta Open curly brace Pq does not start interpolation
|
||||||
.It Ql \e} Ta Curly bracket right
|
.It Ql \e} Ta Close curly brace Pq does not end interpolation
|
||||||
.It Ql \en Ta Newline ($0A)
|
.It Ql \en Ta Newline Pq ASCII $0A
|
||||||
.It Ql \er Ta Carriage return ($0D)
|
.It Ql \er Ta Carriage return Pq ASCII $0D
|
||||||
.It Ql \et Ta Tab ($09)
|
.It Ql \et Ta Tab Pq ASCII $09
|
||||||
.It Ql \e0 Ta Null ($00)
|
.It Ql \e0 Ta Null Pq ASCII $00
|
||||||
.It Qo \e1 Qc \[en] Qo \e9 Qc Ta Macro argument Pq Only in the body of a macro; see Sx Invoking macros
|
|
||||||
.It Ql \e# Ta All Dv _NARG No macro arguments, separated by commas Pq Only in the body of a macro
|
|
||||||
.It Ql \e@ Ta Label name suffix Pq Only in the body of a macro or a Ic REPT No block
|
|
||||||
.El
|
.El
|
||||||
(Note that some of those can be used outside of strings, when noted further in this document.)
|
|
||||||
.Pp
|
.Pp
|
||||||
Multi-line strings are contained in triple quotes
|
Multi-line strings are contained in triple quotes
|
||||||
.Pq Ql \&"\&"\&"for instance\&"\&"\&" .
|
.Pq Ql \&"\&"\&"for instance\&"\&"\&" .
|
||||||
@@ -821,6 +814,7 @@ Section examples:
|
|||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
SECTION "Cool Stuff", ROMX
|
SECTION "Cool Stuff", ROMX
|
||||||
.Ed
|
.Ed
|
||||||
|
.Pp
|
||||||
This switches to the section called
|
This switches to the section called
|
||||||
.Dq CoolStuff ,
|
.Dq CoolStuff ,
|
||||||
creating it if it doesn't already exist.
|
creating it if it doesn't already exist.
|
||||||
@@ -1341,9 +1335,9 @@ below).
|
|||||||
is used to define string constant symbols.
|
is used to define string constant symbols.
|
||||||
Wherever the assembler reads a string constant, it gets
|
Wherever the assembler reads a string constant, it gets
|
||||||
.Em expanded :
|
.Em expanded :
|
||||||
the symbol's name is replaced with its contents.
|
the symbol's name is replaced with its contents, similarly to
|
||||||
If you are familiar with C, you can think of it as similar to
|
.Ic #define
|
||||||
.Fd #define .
|
in the C programming language.
|
||||||
This expansion is disabled in a few contexts:
|
This expansion is disabled in a few contexts:
|
||||||
.Ql DEF(name) ,
|
.Ql DEF(name) ,
|
||||||
.Ql DEF name EQU/=/EQUS/etc ... ,
|
.Ql DEF name EQU/=/EQUS/etc ... ,
|
||||||
@@ -1389,38 +1383,35 @@ PRINTLN "{s}\en"
|
|||||||
String constants can't be exported or imported.
|
String constants can't be exported or imported.
|
||||||
.Pp
|
.Pp
|
||||||
.Sy Important note :
|
.Sy Important note :
|
||||||
When a string constant is expanded, its expansion may contain another string constant, which will be expanded as well.
|
When a string constant is expanded, its expansion may contain another string constant, which will be expanded as well, and may be recursive.
|
||||||
If this creates an infinite loop,
|
If this creates an infinite loop,
|
||||||
.Nm
|
.Nm
|
||||||
will error out once a certain depth is
|
will error out once a certain depth is
|
||||||
reached.
|
reached (see the
|
||||||
See the
|
|
||||||
.Fl r
|
.Fl r
|
||||||
command-line option in
|
command-line option in
|
||||||
.Xr rgbasm 1 .
|
.Xr rgbasm 1 ) .
|
||||||
The same problem can occur if the expansion of a macro invokes another macro, recursively.
|
The same problem can occur if the expansion of a string constant invokes a macro, which itself expands.
|
||||||
.Ss Macros
|
.Ss Macros
|
||||||
One of the best features of an assembler is the ability to write macros for it.
|
One of the best features of an assembler is the ability to write macros for it.
|
||||||
Macros can be called with arguments, and can react depending on input using
|
Macros can be called with arguments, and can react depending on input using
|
||||||
.Ic IF
|
.Ic IF
|
||||||
constructs.
|
constructs.
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
MACRO MyMacro
|
MACRO my_macro
|
||||||
ld a, 80
|
ld a, 80
|
||||||
call MyFunc
|
call MyFunc
|
||||||
ENDM
|
ENDM
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The example above defines
|
The example above defines
|
||||||
.Ql MyMacro
|
.Ql my_macro
|
||||||
as a new macro.
|
as a new macro.
|
||||||
String constants are not expanded within the name of the macro.
|
String constants are not expanded within the name of the macro.
|
||||||
.Pp
|
.Pp
|
||||||
Macros can't be exported or imported.
|
Macros can't be exported or imported.
|
||||||
.Pp
|
.Pp
|
||||||
Plainly nesting macro definitions is not allowed, but this can be worked around using
|
Nesting macro definitions is not possible, so this won't work:
|
||||||
.Ic EQUS .
|
|
||||||
So this won't work:
|
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
MACRO outer
|
MACRO outer
|
||||||
MACRO inner
|
MACRO inner
|
||||||
@@ -1429,7 +1420,9 @@ MACRO outer
|
|||||||
ENDM ; ...and then this is a syntax error!
|
ENDM ; ...and then this is a syntax error!
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
But this will:
|
But you can work around this limitation using
|
||||||
|
.Ic EQUS ,
|
||||||
|
so this will work:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
MACRO outer
|
MACRO outer
|
||||||
DEF definition EQUS "MACRO inner\enPRINTLN \e"Hello!\e"\enENDM"
|
DEF definition EQUS "MACRO inner\enPRINTLN \e"Hello!\e"\enENDM"
|
||||||
@@ -1438,13 +1431,9 @@ DEF definition EQUS "MACRO inner\enPRINTLN \e"Hello!\e"\enENDM"
|
|||||||
ENDM
|
ENDM
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Macro arguments support all the escape sequences of strings, as well as
|
More about how to define and invoke macros is described in
|
||||||
.Ql \e,
|
.Sx THE MACRO LANGUAGE
|
||||||
to escape commas, as well as
|
below.
|
||||||
.Ql \e(
|
|
||||||
and
|
|
||||||
.Ql \e)
|
|
||||||
to escape parentheses, since those otherwise separate and enclose arguments, respectively.
|
|
||||||
.Ss Exporting and importing symbols
|
.Ss Exporting and importing symbols
|
||||||
Importing and exporting of symbols is a feature that is very useful when your project spans many source files and, for example, you need to jump to a routine defined in another file.
|
Importing and exporting of symbols is a feature that is very useful when your project spans many source files and, for example, you need to jump to a routine defined in another file.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -1739,114 +1728,89 @@ Unions may be used in any section, but they may only contain space-allocating di
|
|||||||
.Sx Statically allocating space in RAM ) .
|
.Sx Statically allocating space in RAM ) .
|
||||||
.Sh THE MACRO LANGUAGE
|
.Sh THE MACRO LANGUAGE
|
||||||
.Ss Invoking macros
|
.Ss Invoking macros
|
||||||
A macro is invoked by writing its name at the beginning of a line, followed by any arguments.
|
A macro is invoked by using its name at the beginning of a line, like a directive, followed by any comma-separated arguments.
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
add a, b
|
add a, b
|
||||||
ld sp, hl
|
ld sp, hl
|
||||||
MyMacro ;\ This will be expanded
|
my_macro ;\ This will be expanded
|
||||||
sub a, 87
|
sub a, 87
|
||||||
MyMacro 42 ;\ So will this
|
my_macro 42 ;\ So will this
|
||||||
|
ret c
|
||||||
|
my_macro 1, 2 ;\ And this
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
It's valid to call a macro from a macro (yes, even the same one).
|
After
|
||||||
.Pp
|
|
||||||
When
|
|
||||||
.Nm
|
.Nm
|
||||||
sees
|
has read the macro invocation line, it will expand the body of the macro (the lines between
|
||||||
.Ic MyMacro
|
|
||||||
it will insert the macro definition (the code enclosed in
|
|
||||||
.Ic MACRO
|
.Ic MACRO
|
||||||
/
|
and
|
||||||
.Ic ENDM ) .
|
.Ic ENDM )
|
||||||
.Pp
|
in its place.
|
||||||
Suppose your macro contains a loop.
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
MACRO LoopyMacro
|
|
||||||
xor a, a
|
|
||||||
\&.loop
|
|
||||||
ld [hl+], a
|
|
||||||
dec c
|
|
||||||
jr nz, .loop
|
|
||||||
ENDM
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
This is fine, but only if you use the macro no more than once per scope.
|
|
||||||
To get around this problem, there is the escape sequence
|
|
||||||
.Ic \e@
|
|
||||||
that expands to a unique string.
|
|
||||||
.Pp
|
|
||||||
.Ic \e@
|
|
||||||
also works in
|
|
||||||
.Ic REPT
|
|
||||||
blocks.
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
MACRO LoopyMacro
|
|
||||||
xor a, a
|
|
||||||
\&.loop\e@
|
|
||||||
ld [hl+], a
|
|
||||||
dec c
|
|
||||||
jr nz, .loop\e@
|
|
||||||
ENDM
|
|
||||||
.Ed
|
|
||||||
.Pp
|
.Pp
|
||||||
.Sy Important note :
|
.Sy Important note :
|
||||||
Since a macro can call itself (or a different macro that calls the first one), there can be circular dependency problems.
|
When a macro body is expanded, its expansion may contain another macro invocation, which will be expanded as well, and may be recursive.
|
||||||
If this creates an infinite loop,
|
If this creates an infinite loop,
|
||||||
.Nm
|
.Nm
|
||||||
will error out once a certain depth is
|
will error out once a certain depth is
|
||||||
reached.
|
reached (see the
|
||||||
See the
|
|
||||||
.Fl r
|
.Fl r
|
||||||
command-line option in
|
command-line option in
|
||||||
.Xr rgbasm 1 .
|
.Xr rgbasm 1 ) .
|
||||||
Also, a macro can have inside an
|
The same problem can occur if the expansion of a macro then expands a string constant, which itself expands.
|
||||||
.Sy EQUS
|
|
||||||
which references the same macro, which has the same problem.
|
|
||||||
.Pp
|
.Pp
|
||||||
It's possible to pass arguments to macros as well!
|
It's possible to pass arguments to macros as well!
|
||||||
You retrieve the arguments by using the escape sequences
|
.Bd -literal -offset indent
|
||||||
|
MACRO lb
|
||||||
|
ld \e1, (\e2) << 8 | (\e3)
|
||||||
|
ENDM
|
||||||
|
lb hl, 20, 18 ; Expands to "ld hl, ((20) << 8) | (18)"
|
||||||
|
lb de, 3 + 1, NUM**2 ; Expands to "ld de, ((3 + 1) << 8) | (NUM**2)"
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
You expand the arguments inside the macro body by using the escape sequences
|
||||||
.Ic \e1
|
.Ic \e1
|
||||||
through
|
through
|
||||||
.Ic \e9 , \e1
|
.Ic \e9 , \e1
|
||||||
being the first argument specified on the macro invocation.
|
being the first argument,
|
||||||
.Bd -literal -offset indent
|
.Ic \e2
|
||||||
MACRO LoopyMacro
|
being the second, and so on. Since there are only nine digits, you can only use the first nine macro arguments that way.
|
||||||
ld hl, \e1
|
To use the rest, you put the argument number in angle brackets, like
|
||||||
ld c, \e2
|
.Ic \e<10> .
|
||||||
xor a, a
|
|
||||||
\&.loop\e@
|
|
||||||
ld [hl+], a
|
|
||||||
dec c
|
|
||||||
jr nz, .loop\e@
|
|
||||||
ENDM
|
|
||||||
.Ed
|
|
||||||
.Pp
|
.Pp
|
||||||
Now you can call the macro specifying two arguments, the first being the address and the second being a byte count.
|
This bracketed syntax supports decimal numbers and numeric constant symbols.
|
||||||
The generated code will then reset all bytes in this range.
|
For example,
|
||||||
.Bd -literal -offset indent
|
.Ql \e<_NARG>
|
||||||
LoopyMacro MyVars, 54
|
will get the last argument.
|
||||||
.Ed
|
|
||||||
.Pp
|
.Pp
|
||||||
Arguments are passed as string constants, although there's no need to enclose them in quotes.
|
Other macro arguments and symbol interpolations will also be expanded inside the angle brackets.
|
||||||
Thus, an expression will not be evaluated first but kind of copy-pasted.
|
For example, if
|
||||||
This means that it's probably a very good idea to use brackets around
|
.Ql \e1
|
||||||
.Ic \e1
|
is
|
||||||
to
|
.Ql 13 ,
|
||||||
.Ic \e9
|
then
|
||||||
if you perform further calculations on them.
|
.Ql \e<\e1>
|
||||||
For instance, consider the following:
|
inside the macro body will expand to
|
||||||
.Bd -literal -offset indent
|
.Ql \e<13> .
|
||||||
MACRO print_double
|
Or if
|
||||||
PRINTLN \e1 * 2
|
.Ql DEF v10 = 42
|
||||||
ENDM
|
and
|
||||||
print_double 1 + 2
|
.Ql DEF x = 10 ,
|
||||||
.Ed
|
then
|
||||||
|
.Ql \e<v{d:x}>
|
||||||
|
will expand to
|
||||||
|
.Ql \e<42> .
|
||||||
.Pp
|
.Pp
|
||||||
The
|
Macro arguments are passed as string constants, although there's no need to enclose them in quotes.
|
||||||
.Ic PRINTLN
|
Thus, arguments are not evaluated as expressions, but instead are expanded directly inside the macro body.
|
||||||
statement will expand to
|
This means that they support all the escape sequences of strings (see
|
||||||
.Ql PRINTLN 1 + 2 * 2 ,
|
.Sx String expressions
|
||||||
which will print 5 and not 6 as you might have expected.
|
above), as well as some of their own:
|
||||||
|
.Bl -column -offset indent "Sequence"
|
||||||
|
.It Sy Sequence Ta Sy Meaning
|
||||||
|
.It Ql \e, Ta Comma Pq does not terminate the argument
|
||||||
|
.It Ql \e( Ta Open parenthesis Pq does not start enclosing argument contents
|
||||||
|
.It Ql \e) Ta Close parenthesis Pq does not end enclosing argument contents
|
||||||
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Line continuations work as usual inside macros or lists of macro arguments.
|
Line continuations work as usual inside macros or lists of macro arguments.
|
||||||
However, some characters need to be escaped, as in the following example:
|
However, some characters need to be escaped, as in the following example:
|
||||||
@@ -1868,87 +1832,100 @@ The comma in
|
|||||||
needs to be escaped to prevent it from starting another macro argument.
|
needs to be escaped to prevent it from starting another macro argument.
|
||||||
The comma in
|
The comma in
|
||||||
.Ql PrintMacro2
|
.Ql PrintMacro2
|
||||||
does not need escaping because it is inside parentheses, similar to macro arguments in C.
|
does not need escaping because it is inside parentheses, similar to macro arguments in the C programming language.
|
||||||
The backslash in
|
The backslash in
|
||||||
.Ql \en
|
.Ql \en
|
||||||
also does not need escaping because string literals work as usual inside macro arguments.
|
also does not need escaping because quoted string literals work as usual inside macro arguments.
|
||||||
.Pp
|
.Pp
|
||||||
Since there are only nine digits, you can only access the first nine macro arguments like this.
|
Since macro arguments are expanded directly, it's often a good idea to put parentheses around them if they're meant as part of a numeric expression.
|
||||||
To use the rest, you need to put the multi-digit argument number in angle brackets, like
|
For instance, consider the following:
|
||||||
.Ql \e<10> .
|
.Bd -literal -offset indent
|
||||||
This bracketed syntax supports decimal numbers and numeric constant symbols.
|
MACRO print_double
|
||||||
For example,
|
PRINTLN \e1 * 3
|
||||||
.Ql \e<_NARG>
|
ENDM
|
||||||
will get the last argument.
|
print_double 1 + 2
|
||||||
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Other macro arguments and symbol interpolations will be expanded inside the angle brackets.
|
The body will expand to
|
||||||
For example, if
|
.Ql PRINTLN 1 + 2 * 3 ,
|
||||||
.Ql \e1
|
which will print 7 and not 9 as you might have expected.
|
||||||
is
|
|
||||||
.Ql 13 ,
|
|
||||||
then
|
|
||||||
.Ql \e<\e1>
|
|
||||||
will expand to
|
|
||||||
.Ql \e<13> .
|
|
||||||
Or if
|
|
||||||
.Ql v10 = 42
|
|
||||||
and
|
|
||||||
.Ql x = 10 ,
|
|
||||||
then
|
|
||||||
.Ql \e<v{d:x}>
|
|
||||||
will expand to
|
|
||||||
.Ql \e<42> .
|
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Ic SHIFT
|
.Ic SHIFT
|
||||||
directive is only available inside macros.
|
directive is only available inside macro bodies.
|
||||||
It will shift the arguments by one to the left, and decrease
|
It shifts the argument numbers by one to the left, so what was
|
||||||
.Dv _NARG
|
|
||||||
by 1:
|
|
||||||
.Ic \e1
|
|
||||||
takes the value of
|
|
||||||
.Ic \e2 ,
|
|
||||||
then
|
|
||||||
.Ic \e2
|
.Ic \e2
|
||||||
takes the value of
|
is now
|
||||||
.Ic \e3 ,
|
.Ic \e1 ,
|
||||||
|
what was
|
||||||
|
.Ic \e3
|
||||||
|
is now
|
||||||
|
.Ic \e2 ,
|
||||||
and so forth.
|
and so forth.
|
||||||
|
(What was
|
||||||
|
.Ic \e1
|
||||||
|
is no longer accessible, so
|
||||||
|
.Dv _NARG
|
||||||
|
is decreased by 1.)
|
||||||
.Pp
|
.Pp
|
||||||
.Ic SHIFT
|
.Ic SHIFT
|
||||||
can optionally be given an integer parameter, and will apply the above shifting that number of times.
|
can also take an integer parameter to shift that many times instead of once.
|
||||||
A negative parameter will shift the arguments in reverse.
|
A negative parameter will shift the arguments to the right, which can regain access to previously shifted ones.
|
||||||
.Pp
|
.Pp
|
||||||
.Ic SHIFT
|
.Ic SHIFT
|
||||||
is especially useful in
|
is especially useful in
|
||||||
.Ic REPT
|
.Ic REPT
|
||||||
loops, to repeat the same commands but with different arguments each time.
|
loops to iterate over different arguments, evaluating the same loop body each time.
|
||||||
.Ss Printing things during assembly
|
.Pp
|
||||||
The
|
There are some escape sequences which are only valid inside the body of a macro:
|
||||||
.Ic PRINT
|
.Bl -column -offset indent "Sequence"
|
||||||
and
|
.It Sy Sequence Ta Sy Meaning
|
||||||
.Ic PRINTLN
|
.It So \e1 Sc \[en] So \e9 Sc Ta The 1st\[en]9th macro argument
|
||||||
commands print text and values to the standard output.
|
.It Ql \e<...> Ta Further macro arguments
|
||||||
Useful for debugging macros, or wherever you may feel the need to tell yourself some important information.
|
.It Ql \e# Ta All Dv _NARG No macro arguments, separated by commas
|
||||||
.Bd -literal -offset indent
|
.It Ql \e@ Ta Unique symbol name affix Pq see below
|
||||||
PRINT "Hello world!\en"
|
|
||||||
PRINTLN "Hello world!"
|
|
||||||
PRINT _NARG, " arguments\en"
|
|
||||||
PRINTLN "sum: ", 2+3, " product: ", 2*3
|
|
||||||
PRINTLN STRFMT("E = %f", 2.718)
|
|
||||||
.Ed
|
|
||||||
.Bl -inset
|
|
||||||
.It Ic PRINT
|
|
||||||
prints out each of its comma-separated arguments.
|
|
||||||
Numbers are printed as unsigned uppercase hexadecimal with a leading
|
|
||||||
.Sq $ .
|
|
||||||
For different formats, use
|
|
||||||
.Ic STRFMT .
|
|
||||||
.It Ic PRINTLN
|
|
||||||
prints out each of its comma-separated arguments, if any, followed by a line feed
|
|
||||||
.Pq Ql \en .
|
|
||||||
.El
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Ic \e@
|
||||||
|
escape sequence is often useful in macros which define symbols.
|
||||||
|
Suppose your macro expands to a loop of assembly code:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
MACRO loop_c_times
|
||||||
|
xor a, a
|
||||||
|
\&.loop
|
||||||
|
ld [hl+], a
|
||||||
|
dec c
|
||||||
|
jr nz, .loop
|
||||||
|
ENDM
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
If you use this macro more than once in the same label scope, it will define
|
||||||
|
.Ql \&.loop
|
||||||
|
twice, which is an error.
|
||||||
|
To work around this problem, you can use
|
||||||
|
.Ic \e@
|
||||||
|
as a label suffix:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
MACRO loop_c_times_fixed
|
||||||
|
xor a, a
|
||||||
|
\&.loop\e@
|
||||||
|
ld [hl+], a
|
||||||
|
dec c
|
||||||
|
jr nz, .loop\e@
|
||||||
|
ENDM
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
This will expand to a different value in each invocation, similar to
|
||||||
|
.Ic gensym
|
||||||
|
in the Lisp programming language.
|
||||||
|
.Pp
|
||||||
|
.Ic \e@
|
||||||
|
also works in
|
||||||
|
.Ic REPT
|
||||||
|
blocks, expanding to a different value in each iteration.
|
||||||
.Ss Automatically repeating blocks of code
|
.Ss Automatically repeating blocks of code
|
||||||
Suppose you want to unroll a time consuming loop without copy-pasting it.
|
Suppose you want to unroll a time-consuming loop without copy-pasting it.
|
||||||
.Ic REPT
|
.Ic REPT
|
||||||
is here for that purpose.
|
is here for that purpose.
|
||||||
Everything between
|
Everything between
|
||||||
@@ -2016,9 +1993,9 @@ DEF N = 256
|
|||||||
.Pp
|
.Pp
|
||||||
You can customize the range of
|
You can customize the range of
|
||||||
.Ic FOR
|
.Ic FOR
|
||||||
values, similarly to Python's
|
values, similarly to the
|
||||||
.Ql range
|
.Ql range
|
||||||
function:
|
function in the Python programming language:
|
||||||
.Bl -column "FOR V, start, stop, step"
|
.Bl -column "FOR V, start, stop, step"
|
||||||
.It Sy Code Ta Sy Range
|
.It Sy Code Ta Sy Range
|
||||||
.It Ic FOR Ar V , stop Ta Ar V No increments from 0 to Ar stop
|
.It Ic FOR Ar V , stop Ta Ar V No increments from 0 to Ar stop
|
||||||
@@ -2100,6 +2077,101 @@ This will print:
|
|||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
1, 2, 3, 4, 5 stop! done 5
|
1, 2, 3, 4, 5 stop! done 5
|
||||||
.Ed
|
.Ed
|
||||||
|
.Ss Conditionally assembling blocks of code
|
||||||
|
The four commands
|
||||||
|
.Ic IF , ELIF , ELSE ,
|
||||||
|
and
|
||||||
|
.Ic ENDC
|
||||||
|
let you have
|
||||||
|
.Nm
|
||||||
|
skip over parts of your code depending on a condition.
|
||||||
|
This is a powerful feature commonly used in macros.
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
IF NUM < 0
|
||||||
|
PRINTLN "NUM < 0"
|
||||||
|
ELIF NUM == 0
|
||||||
|
PRINTLN "NUM == 0"
|
||||||
|
ELSE
|
||||||
|
PRINTLN "NUM > 0"
|
||||||
|
ENDC
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Ic ELIF
|
||||||
|
(standing for "else if") and
|
||||||
|
.Ic ELSE
|
||||||
|
blocks are optional.
|
||||||
|
.Ic IF
|
||||||
|
/
|
||||||
|
.Ic ELIF
|
||||||
|
/
|
||||||
|
.Ic ELSE
|
||||||
|
/
|
||||||
|
.Ic ENDC
|
||||||
|
blocks can be nested.
|
||||||
|
.Pp
|
||||||
|
Note that if an
|
||||||
|
.Ic ELSE
|
||||||
|
block is found before an
|
||||||
|
.Ic ELIF
|
||||||
|
block, the
|
||||||
|
.Ic ELIF
|
||||||
|
block will be ignored.
|
||||||
|
All
|
||||||
|
.Ic ELIF
|
||||||
|
blocks must go before the
|
||||||
|
.Ic ELSE
|
||||||
|
block.
|
||||||
|
Also, if there is more than one
|
||||||
|
.Ic ELSE
|
||||||
|
block, all of them but the first one are ignored.
|
||||||
|
.Ss Including other source files
|
||||||
|
Use
|
||||||
|
.Ic INCLUDE
|
||||||
|
to process another assembler file and then return to the current file when done.
|
||||||
|
If the file isn't found in the current directory, the include path list (see the
|
||||||
|
.Fl I
|
||||||
|
option in
|
||||||
|
.Xr rgbasm 1 )
|
||||||
|
will be searched.
|
||||||
|
You may nest
|
||||||
|
.Ic INCLUDE
|
||||||
|
calls infinitely (or until you run out of memory, whichever comes first).
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
INCLUDE "irq.inc"
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
You may also implicitly
|
||||||
|
.Ic INCLUDE
|
||||||
|
a file before the source file with the
|
||||||
|
.Fl P
|
||||||
|
option of
|
||||||
|
.Xr rgbasm 1 .
|
||||||
|
.Ss Printing things during assembly
|
||||||
|
The
|
||||||
|
.Ic PRINT
|
||||||
|
and
|
||||||
|
.Ic PRINTLN
|
||||||
|
commands print text and values to the standard output.
|
||||||
|
Useful for debugging macros, or wherever you may feel the need to tell yourself some important information.
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
PRINT "Hello world!\en"
|
||||||
|
PRINTLN "Hello world!"
|
||||||
|
PRINT _NARG, " arguments\en"
|
||||||
|
PRINTLN "sum: ", 2+3, " product: ", 2*3
|
||||||
|
PRINTLN STRFMT("E = %f", 2.718)
|
||||||
|
.Ed
|
||||||
|
.Bl -inset
|
||||||
|
.It Ic PRINT
|
||||||
|
prints out each of its comma-separated arguments.
|
||||||
|
Numbers are printed as unsigned uppercase hexadecimal with a leading
|
||||||
|
.Sq $ .
|
||||||
|
For different formats, use
|
||||||
|
.Ic STRFMT .
|
||||||
|
.It Ic PRINTLN
|
||||||
|
prints out each of its comma-separated arguments, if any, followed by a line feed
|
||||||
|
.Pq Ql \en .
|
||||||
|
.El
|
||||||
.Ss Aborting the assembly process
|
.Ss Aborting the assembly process
|
||||||
.Ic FAIL
|
.Ic FAIL
|
||||||
and
|
and
|
||||||
@@ -2172,76 +2244,6 @@ to be emitted;
|
|||||||
(the default) will cause a non-fatal error; and
|
(the default) will cause a non-fatal error; and
|
||||||
.Ic FATAL
|
.Ic FATAL
|
||||||
immediately aborts.
|
immediately aborts.
|
||||||
.Ss Including other source files
|
|
||||||
Use
|
|
||||||
.Ic INCLUDE
|
|
||||||
to process another assembler file and then return to the current file when done.
|
|
||||||
If the file isn't found in the current directory, the include path list (see the
|
|
||||||
.Fl I
|
|
||||||
option in
|
|
||||||
.Xr rgbasm 1 )
|
|
||||||
will be searched.
|
|
||||||
You may nest
|
|
||||||
.Ic INCLUDE
|
|
||||||
calls infinitely (or until you run out of memory, whichever comes first).
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
INCLUDE "irq.inc"
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
You may also implicitly
|
|
||||||
.Ic INCLUDE
|
|
||||||
a file before the source file with the
|
|
||||||
.Fl P
|
|
||||||
option of
|
|
||||||
.Xr rgbasm 1 .
|
|
||||||
.Ss Conditional assembling
|
|
||||||
The four commands
|
|
||||||
.Ic IF , ELIF , ELSE ,
|
|
||||||
and
|
|
||||||
.Ic ENDC
|
|
||||||
let you have
|
|
||||||
.Nm
|
|
||||||
skip over parts of your code depending on a condition.
|
|
||||||
This is a powerful feature commonly used in macros.
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
IF NUM < 0
|
|
||||||
PRINTLN "NUM < 0"
|
|
||||||
ELIF NUM == 0
|
|
||||||
PRINTLN "NUM == 0"
|
|
||||||
ELSE
|
|
||||||
PRINTLN "NUM > 0"
|
|
||||||
ENDC
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
The
|
|
||||||
.Ic ELIF
|
|
||||||
(standing for "else if") and
|
|
||||||
.Ic ELSE
|
|
||||||
blocks are optional.
|
|
||||||
.Ic IF
|
|
||||||
/
|
|
||||||
.Ic ELIF
|
|
||||||
/
|
|
||||||
.Ic ELSE
|
|
||||||
/
|
|
||||||
.Ic ENDC
|
|
||||||
blocks can be nested.
|
|
||||||
.Pp
|
|
||||||
Note that if an
|
|
||||||
.Ic ELSE
|
|
||||||
block is found before an
|
|
||||||
.Ic ELIF
|
|
||||||
block, the
|
|
||||||
.Ic ELIF
|
|
||||||
block will be ignored.
|
|
||||||
All
|
|
||||||
.Ic ELIF
|
|
||||||
blocks must go before the
|
|
||||||
.Ic ELSE
|
|
||||||
block.
|
|
||||||
Also, if there is more than one
|
|
||||||
.Ic ELSE
|
|
||||||
block, all of them but the first one are ignored.
|
|
||||||
.Sh MISCELLANEOUS
|
.Sh MISCELLANEOUS
|
||||||
.Ss Changing options while assembling
|
.Ss Changing options while assembling
|
||||||
.Ic OPT
|
.Ic OPT
|
||||||
|
|||||||
Reference in New Issue
Block a user