Labels

Labels are mainly used to hold numerical values. This comes in handy because we humans are better in remembering names than meaningless values. For this reason labels play a very important role in assemblers.

Labels can hold different types of values like constants, addresses, offsets, SFRs, bit patterns etc. The SB-Assembler only remembers the label's value, not what type of value it is holding. This means that you can use these values for any purpose without bothering about type conversion. This doesn't only give you more freedom as a programmer, it also gives you more responsibility.
The value is always stored as a 32 bit value regardless of the original data size. The actual size used while referencing the label depends on the operand type used. This value will be truncated to the numbers of bits which actually will fit into the operand, without a warning or error.

For processors which use more than one byte per instruction, like the AVR and PIC processors, a boundary Sync is performed whenever a label is declared in program memory. A label can not point to halfway within an instruction because the processor won't be able to jump to that label anyway.

Label Declaration

Label declarations always start at column 0 of the program line. An optional colon : may follow the label name. This colon is only accepted for compatibility reasons with other assemblers and serves no particular purpose. The label name should be followed by a white space, which is a space, a TAB or an EOL.

The label can get its value in several different ways:

  • The .EQ directive (or = ) can be used to assign the value of an expression to the label. The expression must evaluate without errors or forward references to other labels. The value which is assigned to the label is a constant value, which means that it may not be changed anymore. Any attempt to change the value of a label, once it is assigned, will result in an error.
  • The .SE directive is used to assign a variable value to the label. The .SE directive works exactly the same as the .EQ directive. The only difference is that the value may be changed as often as you want. You cannot change a constant label to a variable label, or vice versa.
  • In all other declarations the current Program Counter value is stored as the label's value. Again this value is a constant and may not be changed anymore.

Labels may be declared only once. The value they get is fixed and may not be changed anymore. The only exception to this rule are labels that get their value from the .SE directive, their value is variable and may be changed as often as you like.
If the assembler tries to declare a label that already exists it checks if the new value is the same as it was when the label was declared for the first time. If it is, the new declaration will be ignored and the original value of the label is not changed. However the SB-Assembler reports an "Extra definition error if the new declaration value differs from the original one, in which case the label's value hasn't been changed.

Forward Referencing

In a 2-pass assembler, like the SB-Assembler, labels can be used (referenced) before they are declared. All label values should be resolved at the end of the 1st pass though. Their actual values are used in the 2nd pass. Using, or referencing, labels which are not yet declared is called forward referencing.
Forward referencing can sometimes cause some problems. Some instructions or directives don't allow the use of forward referenced labels in their operands. E.g. forward referencing is not allowed while assigning a value to another label. Sometimes the length of an operand is variable, depending on the size of its value. The assembler can pick the most appropriate addressing mode if the value is known. With forward referencing the size of the value is not yet known during pass 1. Thus the assembler must expect the worst case and use the longest addressing mode available.

Note: Most Crosses which support variable length addressing modes allow you to force the use of the shortest addressing mode by preceding the expression by the < symbol. Be careful though with that function! The assembled program may fail, big time, without warning if the address doesn't fit in the short addressing mode! It should only be used when you are sure the forward referenced address will fit in the short addressing mode.
When you're in doubt it is better not to use this function at all, at the penalty of wasting some (valuable) bytes of program memory and some instruction cycles.

Reserved Names

Label names should not be the same as reserved names. To begin with, there are no reserved names known to the SB-Assembler, so any names can be given to your labels.
However some Crosses do have reserved names! They usually are names of registers like A, R1, SP, IX etc. Even though you can use these names for your labels it is better to avoid doing so to prevent confusion. Unpredictable behaviour may be the result if you do use reserved names as label names. Some Crosses may interpret the reserved names before your labels, others may interpret them the other way around. The assembler will not warn you if you use reserved names.
The best way to avoid using reserved names is making your label names longer than 2 characters because most of the reserved names are 1 or 2 characters long.

Label Types

The SB-Assembler knows 3 types of labels:

  • Global labels, which can be referenced throughout the entire program.
  • Local labels, which "live" from the previous Global label until the next Global label.
  • Macro labels, which only "live" during a macro expansion.

Label names are case insensitive which means that there's no difference between upper and lower case characters. The label name may be of any length, up to 255 characters. However only the first 32 characters are actually remembered by the assembler. This means that the assembler will not notice differences in names beyond the 32nd character.
This limitation of the name length only exists for Version 2 of the SB-Assembler. Version 3 has no real limits on the label's name length.

A Global label name starts with a character from A to Z and may further contain any characters from A to Z, the digits 0 to 9, the underscore _ and a dot . for all subsequent characters. The SB-Assembler stops parsing the label name if any other character is encountered. Some assemblers require a colon : behind the label name during declaration. With the SB-Assembler this colon is optional and serves no particular purpose, other than perhaps readability.
Please note that this colon is only allowed during the declaration of a label. The colon is NOT allowed when the label is used (referenced) in an expression.
As of Version 3.01 Global label names may also start with an underscore. Many software engineers prefer to start labels for system properties with an underscore.

Some examples of Global labels:

RESET         ; Example of a global label
CharOut       ; Mixed case, doesn't matter
KEY_IN        ; Underscore is a legal character
SAMPLE.LABEL  ; And so is a dot
EXIT30        ; And digits
WITHCOLON:    ; Trailing colon is optional
_OPTION       ; Beginning with _ is allowed as of Version 3.1

A Local label name starts with a dot and follows the same rules as Global labels for all subsequent characters. The character following the dot doesn't necessarily have to be a character from A to Z. The dot is also counted as character in the name length (Only Version 2 of the SB-Assembler).

Some examples of Local labels:

.LOOP    ; A typical local label
.2       ; A local label can start with a digit
.Again   ; Mixed case is no problem
.SKIP:   ; Trialing colon is optional

A Macro label name starts with a colon, which is the only difference from Local label names when it comes to syntax.

Some examples of macro labels:

:LOOP    ; A typical local label
:3       ; A local label can start with a digit
:Again   ; Mixed case is no problem
:SKIP:   ; Trialing colon is optional

Global Labels

Global labels can be accessed throughout the entire program. It doesn't matter that they are declared in other include files either. In fact there is only one name space, which holds all Global labels and their values in the SB-Assembler.

The use of Global labels has some small, but important side effects. Every time a Global label is declared, all previously declared Local labels become inaccessible. They are not forgotten though, you simply can't reach them anymore.
At the same time the Macro expansion counter is reset to 0 every time you declare a new Global label. That way you can virtually expand an endless number of pre-defined Macros in your assembly program, without risking an internal counter overflow.

Local Labels

Local labels are one of the most interesting features of the SB-Assembler. Strangely enough most assemblers must do without them.

Label names should be as descriptive as possible to keep the program readable for us humans. But inventing unique and meaningful names becomes more and more difficult when our program grows longer and longer. Especially if you have to use unique names for loops and skips throughout a long program too. In many assembly programs you see label names like LOOP217, SKIP_XXX, or even more meaningful names like XXXX and X127.
Local labels take away a large burden from the programmer for they can be re-used again and again. E.g. you can use the Local label .LOOP as often as you want.
Every time you define a new Global label, all previous Local labels are discarded, so you can start with a clean slate again.

An example using label .LOOP twice

DELAY100   MOV   R1,#100
.LOOP      DEC   R1
           JNZ   .LOOP
           RET

; The next line makes the SB-Assembler forget all Local label

DELAY10    MOV   R1,#10
.LOOP      DEC   R1
           JNZ   .LOOP
           RET

As you can see the Local label .LOOP is declared twice. This is perfectly legal because the first instance only "lives" from DELAY100 until but not including DELAY10. The first JNZ instruction jumps back to the first instance of the Local label .LOOP. The second JNZ jumps back to the second Local label .LOOP because the first one is not accessible anymore.

Local labels may not be declared until at least one Global label is declared, otherwise the SB-Assembler will report a Missing Global label error. In Version 2 of the SB-Assembler it is also not allowed to declare a Local label directly after a macro definition, until a new Global label is declared. This is done because macro definitions are stored in the same symbol table as labels.
Version 3 doesn't have this restriction. However, one should consider if it makes any sense to continue with the declaration of a local label, directly after a macro definition.

With Version 3 of the SB-Assembler it is now possible to access Local labels belonging to other Global labels. You do that by adding the Global label, to which the desired Local label belongs, in front of the Local label, separated by a colon and omitting the first dot of the Local label.

A silly example

DELAY100   MOV   R1,#100
.LOOP      DEC   R1
           JNZ   .LOOP
           RET

; The next line makes the SB-Assembler forget all Local label

DELAY10    MOV   R1,#10
.LOOP      DEC   R1
           JNZ   DELAY100:LOOP
           RET

In this silly example the second JNZ instruction now jumps back to the first Local label .LOOP . The Global label is separated from the Local label by a colon, while the first dot of the Local label is omitted.

A more useful example is the imitation of a data set. The SB-Assembler doesn't really know the concept of data sets, but you can imitate them.

A data set imitation example

DATASET    .OR   $50        Beginning of the data set
.COUNTER   .BS   2          A 2 byte wide counter
.VALUE     .BS   1          A 1 byte long value
.ERROR     .BS   1          A 1 byte long error value
.RESULT    .BS   4          A 4 byte long result

INCCOUNT   INC   DATASET:COUNTER   Increment low byte of counter
           BNE   .NOCARRY          No carry to high byte!
           INC   DATASET:COUNTER+1 Increment high byte of counter
.NOCARRY   RTS

Please note that Global labels and Local labels must be declared on separate lines. For instance you can't declare the label DATASET:COUNTER in one blow. You'd have to declare DATASET first, and then on a separate line you should declare label .COUNTER .

Only Local labels may be combined with Global labels this way. It is not possible (nor desirable) to do this with Global labels and macro labels. Even if the colon may suggest that it should work with macro labels too.

Macro Labels

Macro labels are very similar to Local labels, in fact outside Macros they work exactly the same. Outside macros, Local labels and Macro labels may even be interchanged in Version 3 of the SB-Assembler. Thus label .LOOP is the same label als label :LOOP (Only in Version 3).
However there is a small but significant difference in operation between Local labels and Macro labels within Macro expansions.

What exactly is the problem with normal Global and Local labels within an expanding Macro? Suppose I declare a normal Global label within a Macro. Then I could use (expand) this Macro only once because the Global label would be declared again if I want to expand the Macro for a second time. But the label will probably get a different value the second time. This is not acceptable and we have to think of another way of handling this.
Local labels give a slight improvement because we can re-use them every time a new Global label is declared. But what if we want to expand the Macro twice or more without declaring new Global labels in between?
That's where Macro labels come in. Every time a Macro is expanding it is automatically assigned a new Macro number internally. It's this Macro number that is added to the Macro label names (internally) to make them unique. Therefore Macro labels "live" only in the current expansion of the Macro. You can't reference Macro labels from outside its current expansion.
The Macro number is reset every time a new Global label is declared. In Version 2 of the SB-Assembler up to 254 different Macro numbers may be used before a new Global label must be declared to reset the Macro number again. In Version 3 this maximum number is increased to 999.

Macro labels may not be used until at least one Global label is declared, otherwise the SB-Assembler will report a Missing global label error".

More detailed information about Macro labels can be found in the special chapter about Macros.