Back Home

Navigation

Home

SB-Assembler
News
Download
Quick Start
Source Files
Running SBASM
Expressions
Labels
Directives
Macros
Error Messages
How To?
History
Known Bugs

Cross-Overlays

Control
.CP .CR .TF
.TW .EQ .SE
.BI .CH .IN
.OR .BS .NO
.PH .EP  
.DU .ED  
Data
.AS .AT .AZ
.DA .DL .DR
.DB .DW .HS
.RF    
Conditional
.DO .EL .FI
.MA .EM .XM
List
.LI .CO .EC
.EF .LF .SF
.EB .EN .ST
.PG .LM .TI
.EJ .ER  
Alphabetical
.AS .AT .AZ
.BI .BS .CH
.CO .CP .CR
.DA .DB .DL
.DO .DR .DU
.DW .EB .EC
.ED .EF .EJ
.EL .EM .EN
.EP .EQ .ER
.FI .HS .IN
.LF .LI .LM
.MA .NO .OR
.PG .PH .RF
.SE .SF .ST
.TA .TF .TI
.TW .XM  

Directives

A directive is a command to the assembler and thus it is not an instruction for the target microprocessor. Directives are often called pseudo instructions because they appear in the instruction field of the source line. Directives are always placed in the instruction field on program lines and may be followed by one or more operands.
The SB-Assembler uses a special notation for directives. All directives start with a dot, followed by 2 characters. This means that existing code must be changed to represent the SB-Assembler convention when it comes to directives. However this can easily be done with the replace command found in many text editors.

SB-Assembler directives always begin with a dot which is followed by two or more characters. This makes it easier to distinguish directives from mnemonics and avoids interference with future mnemonics on new Crosses.
All directives consist of 2 characters, which are usually an abbreviation or acronym of the full directive's name. The SB-Assembler only checks the first 2 characters following the dot to see if it is a legal directive. All other characters following the first 2 are ignored until the next space, TAB or EOL.
Most directives are common to all Cross-Overlays. But each Cross-Overlay can have it's own set of additional directives, e.g. the 6809 Cross knows the .DP directive which sets the Direct Page.
Some Cross-Overlays may also change the behaviour of some of the standard directives to suit the needs or peculiarities of the serviced processor type.
Such Cross specific directives only exist as long as the Cross-Overlay is loaded into memory.

Some directives must or may be followed by one or more parameters. Those parameters may not contain space or TAB characters because that will signal the end of the parameter. Only literal strings may contain spaces as long as they are properly enclosed in delimiters.
Parameters must be separated from each other by a comma. The SB-Assembler stops interpreting parameters as soon as it finds a space, TAB or EOL character.

Document Conventions

I use some common document conventions in the following description of the directives.
Optional parameters that may follow the directives are enclosed in square brackets [ ]. For example [-]string means that the - sign is an optional part of the parameter.

Text printed in Italic font should not be typed literally but indicates the type of the expected parameter. For example filename should be replaced by the real file name, possibly including drive and path. File names and paths are restricted to the normal MS-DOS 8.3 file names.
Directives that use file names sometimes assume a default extension suitable for the function. For example the .IN directive assumes the extension to be .ASM if it is omitted. This doesn't mean that you are not able to use other extensions. If the extension you want to use differs from the default extension it must be given explicitly.
Some directives also allow you to use device names in stead of file names like LPT1: COM1: or PRT:. Device names must always end in a colon.

Sometimes you can use one of several options. These options are separated by a pipe ¦ symbol. For example on¦off means you may either use on or off. Notice that on and off are not printed in Italic, so they should be typed literally.

Strings should be delimited. This means that a legal delimiting character must be used to enclose the string. All characters in between the two delimiters are treated literally, spaces and upper and lower case are retained.
Almost any character may be used as delimiter. Only the characters dash - , a comma , , a dot . , a colon : and the character A to Z are not allowed to be used as delimiter. Often used delimiters are " ' / \ ! ¦ .
The delimiter itself may not be used inside the string because that would end the string literal. The full standard ASCII character set with values between $32 and $126 can be used as string characters. Characters from the extended IBM character set are not allowed in strings and will have unpredictable results.

Expressions can be composed of constant values in any of the available radixes, labels and calculations. These calculations always result in a 32 bit value. The directive decides how many of the 32 bits are really used.

.AS    Ascii String

Syntax:

        .AS  [-]string¦#expression[,string¦#expression[,...]]

See also: .AT .AZ .DA .DB .DL .DR .DW .HS .RF

Function:

The .AS directive converts ASCII strings and/or expressions to hexadecimal bytes.

Explanation:

The string parameter is a delimited string. The expression should evaluate to a positive number that is less than 256. The parameter can consist of more than one string or expression, which all should be separated from each other by commas.
All generated bytes will have bit b7=0 if the first character of the parameter is not a - sign, this is called positive ASCII. If the first character of the parameter is a - sign all generated bytes will have b7=1, this is called negative ASCII.
The delimiters may not enclose an empty string. They should enclose at least one character.

Examples:

0000-54 65 73 74           .AS  /Test/
0004-D4 E5 F3 F4           .AS  -/Test/
0008-0D 54 65 73
000C-74 0A 0D              .AS  #$0D,/Test/,#$0A,#$0D
000F-8D D4 E5 F3
0013-F4 8A 8D              .AS  -#$0D,/Test/,#$0A,#$0D
0016-54 65 73 74
001A-0D 54 65 73
001E-74                    .AS  /Test/,#$0D,\Test\
.AT    Ascii string Terminated

Syntax:

        .AT  [-]string¦#expression[,string¦#expression[,...]]

See also: .AS .AZ .DA .DB .DL .DR .DW .HS .RF

Function:

The .AT directive converts ASCII strings and/or expressions to hexadecimal bytes. The last generated byte will have an inverted bit b7 to signal the end of the string. Apart from this minor difference the .AT directive works exactly the same as the .AS directive.

Explanation:

The string parameter is a delimited string. The expression should evaluate to a positive number that is less than 256. The parameter can consist of more than one string or expression, which all should be separated from each other by commas.
All generated bytes except the last one will have bit b7=0 if the first character of the parameter is not a - sign, this is called positive ASCII. If the first character of the parameter is a - sign all generated bytes will have b7=1 except the last one, this is called negative ASCII.
The delimiters may not enclose an empty string. They should enclose at least one character.

Examples:

0000-54 65 73 F4           .AT  /Test/
0004-D4 E5 F3 74           .AT  -/Test/
0008-0D 54 65 73
000C-74 0A 8D              .AT  #$0D,/Test/,#$0A,#$0D
000F-8D D4 E5 F3
0013-F4 8A 0D              .AT  -#$0D,/Test/,#$0A,#$0D
0016-54 65 73 74
001A-0D 54 65 73
001E-F4                    .AT  /Test/,#$0D,\Test\
.AZ    Ascii string terminated by Zero

Syntax:

        .AZ  [-]string¦#expression[,string¦#expression[,...]]

See also: .AS .AT .DA .DB .DL .DR .DW .HS .RF

Function:

The .AZ directive converts ASCII strings and/or expressions to hexadecimal bytes. The last generated byte will be followed by a byte with the value of $00 to signal the end of the string. Apart from this minor difference the .AZ directive works exactly the same as the .AS directive.

Explanation:

The string parameter is a delimited string. The expression should evaluate to a positive number that is less than 256. The parameter can consist of more than one string or expression, which all should be separated from each other by commas.
All generated bytes will have bit b7=0 if the first character of the parameter is not a - sign, this is called positive ASCII. If the first character of the parameter is a - sign all generated bytes will have b7=1 except the trailing $00 byte, this is called negative ASCII.
The delimiters may not enclose an empty string. They should enclose at least one character.

Examples:

0000-54 65 73 74
0004-00                    .AZ  /Test/
0005-D4 E5 F3 F4
000A-00                    .AZ  -/Test/
000B-0D 54 65 73
000F-74 0A 0D 00           .AZ  #$0D,/Test/,#$0A,#$0D
0013-8D D4 E5 F3
0017-F4 8A 8D 00           .AZ  -#$0D,/Test/,#$0A,#$0D
001B-54 65 73 74
001F-0D 54 65 73
0023-74 00                 .AZ  /Test/,#$0D,\Test\
.BI    Binary Include

Syntax:

        .BI  filename.ext[,format]

See also: .CH .IN

Function:

The .BI directive copies the contents of a binary file to the current target file from the current location. This enables you to include for example sampled speech, HTML pages, or images in your programs.

Explanation:

The filename may contain drive letter and path name. If no path is given the current directory should hold the file to be included. No default extension is assumed, so if the file has an extension it should be included in the filename.

Binary include files can not be nested. Binary include files can't open other include files by themselves, but it is also not allowed to include a binary file from within a normal include file.

If no format is specified the binary include file will be treated as a plain binary file. All bytes are copied as they appear in the file. No attempt is made by the SB-Assembler to figure out in what format the file originally was written!

The format parameter can have any of the following names:

  BINUnformatted binary file (default)
  E52Elector's EMON52 format
  FPCFour Packed Code formatted file
  HEXUnformatted HEX file
  INTIntelHex formatted file
  MOTMotorola S19, S28 or S37 formatted file
  SIGSignetics formatted file
  TEKTektronix formatted file

In fact only the first character of the format name is sufficient to select a particular file format. All other characters on the program line following that character will be ignored and treated as remarks.

Please Note: That the Motorola format is called MOT here, and not S19, S28 or S37 like it is with the .TF directive. Using S19, S28 or S37 as parameter will result in a *** Binary format error messages if you feed a Motorola formatted file because the SB-Assembler is expecting a Signetics formatted file (which starts with an S).

Address fields of all formatted file formats are ignored. Segment records in Intel HEX files only carry address information and will be ignored too. All data bytes are copied in the order of appearance in the binary include file.
The address field of the FPC formatted files is optional and is also ignored if it is given.

Formatted files don't have to be terminated with the end of file record. No error is given if the end of file record is omitted.

Formatted files may contain remark lines. An empty line or a line beginning with ! ; * " or ' will be treated as a remark line.
Records in a formatted file may not contain any spaces. Leading and trailing spaces are ignored though. The only exception to this rule is the EMON52 format where bytes are separated by spaces by default.
The binary include file will be terminated immediately if any error (error in the expected format or disk error) is encountered.

If a label is present in the label field of the source line containing the .BI directive it will be assigned the address of the first byte of the binary include file.

A program line that contains a .BI directive can be listed if the list option is switched on. The generated bytes are never listed.

Examples:

0000-            BITMAP   .BI  SAMPLE,INT
.BS    Block Skip

Syntax:

        .BS  expression1[,expression2]

See also: .DU .ED .EP .NO .OR .PH .RF

Function:

With .BS you can skip a block of memory. The number of bytes to be skipped is determined by expression1. The skipped bytes can be filled with the 8 bits value of expression2.
The .BS directive is often used in combination with the .DU and .ED directives to define RAM variables.

Explanation:

Expression1 may not contain forward referenced labels, otherwise a fatal "Undefined label error" will be reported.

The value of expression1 can range from 0 to $FFFFFFFF, although it is not very likely that you're going to use the maximum value. If the value is 0 no bytes are skipped at all.
The maximum value of expression2 is $FF. Larger values will simply be truncated at the lowest byte before they are used. Thus a value of $100 will fill the skipped memory with the value of $00.

The .BS directive is often used to declare RAM buffers and RAM variables. Normally it is not very useful to declare buffers in ROM memory because ROM values can not be changed afterwards anyway.

Operation of the .BS directive differs a little between formatted and unformatted target files.
With unformatted target files a filling value is always used, whether expression2 is given or not. If expression2 is omitted the value $00 is used to fill the skipped memory.
With formatted target files a filling value is only used if expression2 is given. Otherwise the skipped memory block will be skipped completely. The current data record is terminated and a new one is started with the new target address in the address field.
The only exception to this rule is when the number of bytes skipped is less than the line record length of the target file. In that case bytes with the value of $00 are used to fill the skipped memory.

The list file will only contain the first address of the skipped memory block. The filled bytes are not listed in the list file.

Examples:

0000-                      .OR  $0000     Define RAM memory
0000-                      .DU            but don't produce any code
0000-            PNTR      .BS  2         Define a 2 bytes pointer
0002-            CNTR      .BS  2         Define a 2 bytes counter
0004-            TEMP      .BS  1         Define a 1 byte temp location
0005-            FLAGS     .BS  1         Define a flags byte
0006-            KEYIN     .BS  1         Last pressed key (1 byte)
0007-            DSPPNT    .BS  1         Display buffer pntr (1 byte)
0008-            DSPBUF    .BS  6         Define a 6 byte display buffer
000E-                      .ED            End of dummy block
8000-                      .OR  $8000     Begin of the program in ROM
8000-                      .BS  $100,$FF  Skip part of ROM memory
8100-            ;                         and fill it with $FF

Please note that no code is generated in the .DUmmy block. Only the addresses are assigned to the appropriate labels.

.CH    CHain file

Syntax:

        .CH  filename[.ext]

See also: .BI .IN

Function:

With the .CH directive you can CHain include files together without going back to the main source file first.

Explanation:

The .CHain directive works exactly the same as the .INclude directive if it's encountered in the main source file. It remembers where we are in the main source file, opens a new source file and starts assembling from the beginning of that new source file. If the new source file is finished, it is closed and we continue where we left off in the main source file.

But if the .CHain directive is encountered inside an include file it will close the current include file immediately, opens the new .CHained file and starts assembling from the top of this new file. This effectively chains the new include file to the previous include file without going back to the main source file first.

Please note that all lines that follow the .CH directive in an include file are ignored by the SB-Assembler. They are not even treated as comment lines because they will never be listed in list files. The program line containing .CH, when encountered inside an include file, is always the last line of the file that is interpreted and listed in the list file.

The .CH directive must be followed by a filename, which may be preceded by a drive letter and a path name according to the normal MS-DOS rules.
The extension .ext is optional. If the extension is omitted the default assembler source extension .ASM is used.

Examples:

         .IN   DECLARE           Called from the main source file
 
LABEL    .EQ   10                Imaginary part of the .INclude file
          :
          :
          :
ANOTHER  .EQ   $FF
         .CH   C:\LIB\MACRO.LIB  Chain to the file MACRO.LIB 

MACRO    .MA                     First line of the chained source file
          :
          :
          :
         .EM                     Last line of the chained source file

         NOP                     We're back in the main source file
.CO    COmment

Syntax:

        .CO

See also: .EB .EC .EN .ER .ST

Function:

The .CO directive starts a comment block which can be filled with any remarks. It may also be used to temporarily comment out part of your code during debugging.
With the .CO directive you can implement large blocks of remarks without the need to start every line with a semicolon or asterisk.

Explanation:

The part of your source file that should be ignored by the SB-Assembler can be enclosed between the opening directive .CO and the closing directive .EC. All lines in between will be treated as if they all start with a semicolon or asterisk. They will be listed in list files, but the syntax is not checked nor will any code be generated.

It is possible to define a label together with the .CO directive on the same source line. All text following the .CO directive on the same source line will be ignored.
All following lines of the source file will also be ignored until the .EC directive is encountered in the operand field of the source line.

The .COmment mode will automatically be terminated if the physical end of the source file is reached.

Examples:

        .CO             Beginning of the comment block
Anything is allowed in this comment block.
You don't have to start the line with ; or *
; Although it won't hurt if you do.

        .CO             It is not possible to nest comment
blocks. The last .CO directive is treated as a comment itself.
The next .EC directive will end the complete .COmment mode.

        LD    A,B      Is not assembled
        .DO   A>B      Has no effect
        .IN   FILE     Just skipped
        .EN            Not even this is interpreted

        .EC            End of comment block, at last.
.CP    Com port Parameters

Syntax:

        .CP  comport,baudrate,parity,databits,stopbits

See also: .EF .EJ .LF .LI .LM .PG .SF .TF .TI .TW

Function:

The .CP directive sets the communication parameters of the select serial COM port. This is useful if you intend to send the generated object file directly to a programmer or EPROM simulator connected to the COM port.

Explanation:

I have added this directive to be able to set the communication parameters of the serial port in case you intend to send the target file directly to a device connected to a COM port.

All parameters are to be entered in the order indicated under the heading "Syntax".

comport
This is an expression that must evaluate to a legal DOS COM port number. Usually this in the range from 1..4, but all ports don't necessarily exist depending on your hardware. Only 1..16 is accepted as values, otherwise you'll get a "Range error".

baudrate
This is the baud rate you wish to use for communication. The expression should evaluate to one of the following baud rates, otherwise you'll get a Range error

110
150
300
600
1200
2400
4800
9600
19200

parity
This is the parity you wish to use. The parity is indicated by a letter N (none), E (even), or O (odd). Other letters will generate an Illegal parameter error

databits
This expression should evaluate to a value of 7 or 8. Other values will result in a Range error.

stopbits
This expression should evaluate to a value of 1 or 2. Other values will result in a Range error.

Please note that the COM port parameters are only set during pass 2 of the assembly process.

Examples:

        .CP  1,9600,N,8,1       Set COM1 to 9600 baud, No parity,
;                                8 data bits and 1 stop bit.
.CR    CRoss-overlay load

Syntax:

        .CR  filename[.ext]

Function:

The .CR directive loads a Cross-Overlay into memory.

Explanation:

This is one of the most powerful directives of the SB-Assembler. It loads a Cross-Overlay into memory. This allows the SB-Assembler to assemble programs for almost any type of processor. It can even be used to switch between different Cross-Overlays in one assembly run to create a program for different processors at same the time.

The .CR directive must be followed by a filename which may be preceded by a drive letter and/or path name.
The extension .ext is optional and if it is omitted the default extension .SBA is used.
If no drive letter and/or path name are given the overlay is searched for in the current directory. If it can't be found there the search continues in the parent directory of the SB-Assembler which is the directory from which the program sbasm.com originated. So normally it is not necessary to include drive and path names. It's even better not to include them at all.
If the requested Cross-Overlay is already resident in memory it will not be loaded again. This is usually the case at the start of the second pass of the assembler.

As soon as the Cross-Overlay is loaded into memory it will be initialized. This means that some default values are set, like the endian model (the order in which multiple byte values are stored in memory). Also Cross-Overlay specific settings are set to their default value, e.g. the .DP value for the 6809 Cross-Overlay will be reset to $00.
Please note that this initializing is also done if the Cross-Overlay was already resident in memory!

It is even possible to have more than one Cross-Overlay loaded during one assembly run. This enables you to create programs for mixed processor types.
One of the best examples for such a situation was the Apple ][ computer which had a native 6502 processor and an optional Z80 installed. The 6502 should initialize the system and handle I/O while the Z80 might be doing the hard work. Please note that both processors were sharing the same memory busses. To write programs for such a system requires an assembler that can handle more than one processor type at the same time. The SB-Assembler is such an assembler!
Another example could be a programming device to program Motorola processors. These processors need a little bootstrap loader to be uploaded before they can accept the code that must be written into EEPROM. The programmer itself can be made with any type of processor, e.g. the 8052. But the little bootstrap loader code must be written in the target processor's language. The 8052 treats that piece of code as data while the target processor accepts is as executable code.
There is no limit to the number of Cross-Overlay switches in an assembly run to the SB-Assembler's point of view. Practically it may be difficult to implement the resulting code in most cases though ;-)

Also note that the SB-Assembler doesn't know any mnemonics of any processor type until a Cross-Overlay is loaded into memory. The .CR is best used before any code is generated by the assembler because the Cross-Overlay determines the endian model, which is the order in which multiple byte values are stored in memory.

Examples:

        .CR    Z80            Load the Z80 Cross-Overlay from
;                              the current directory or from
;                              the parent directory where the
;                              sbasm.com program originated
        .CR    \SBASM\6502    Load the 6502 Cross-Overlay
;                              from the directory \SBASM\ of the
;                              current drive.
.DA    DAta

Syntax:

        .DA  [#¦/¦=¦\]expression[,[#¦/¦=¦\]expression[,...]]

See also: .AS .AT .AZ .DB .DL .DR .DW .HS .RF

Function:

The .DA directive is used to enter bytes and words of data into the target code. The data is entered as one or more expressions, separated from each other by commas.

Explanation:

Every expression following the .DA directive will be evaluated and the lower 16 bit value of the result is stored in the target file. The order in which the bytes are stored depends on the loaded Cross-Overlay. Some processors prefer to have the lowest byte stored first, others want the highest byte stored first. So please refer to the description of the particular Cross-Overlay to see in what order the bytes are stored.
The default order, when no Cross-Overlay is loaded, is lowest byte first. This is also known as little endian model.

The .DA directive can also be used to store single bytes in the target file. To store single bytes the expression must be preceded by one of the symbols:

# stores the lowest byte of the 32 bit result (b0..b7)
/ stores the 2nd lowest byte (b8..b15)
= stores the 2nd highest byte (b16..b23)
\ stores the highest byte (b24..b31)

The lowest 16 bits are stored if none of these prefixes is used.

Data bytes and words can be mixed together on the same .DA directive line. Multiple expressions should be separated by commas.

Important: Be sure to load the appropriate Cross-Overlay before using the .DA directive! Otherwise the first data words may be saved in the wrong order (wrong endian model).

I have included the .DR directive for those cases where you need the opposite endian model.

Examples:

0000-09 53 7B 23
0004-61 E1               .DA    #%1001,#@123,#123,#$123,#'a',#"a"
0006-78                  .DA    #$12345678
0007-56                  .DA    /$12345678
0008-34                  .DA    =$12345678
0009-12                  .DA    \$12345678
000A-34 12               .DA    $1234               Notice the byte order
000C-7C                  .DA    #5+$80-%1001
000D-34 12 56            .DA    $1234,#$56          Mixed words and bytes
.DB    Define Byte

Syntax:

        .DB  [expression | string[,[expression | string[,...]]

See also: .AS .AT .AZ .DA .DL .DR .DW .HS .RF

Function:

The .DB directive is used to enter bytes only and is meant to add some compatibility with other assemblers in the market. Operation of the .DB directive is almost the same as the DB directive found in most assemblers. Personally I prefer the use of the more powerful .DA directive.
Porting existing software to the SB-Assembler will become a little easier with this directive.

Explanation:

Every expression following the .DB directive will be evaluated and only the lower 8 bit value of each result is stored in the target file. If you need other bytes of the 32-bit result you can divide the result by $100, $10000 or $1000000.

Instead of an expression you may also enter a string of characters. Strings must be surrounded by a pair of single or double quotes. The string may not be empty and must be terminated with the same type of quote as it was opened. The opening quote may not be present in the string itself because that would terminate the string prematurely.
There is no difference between using a pair of single quotes or a pair of double quotes, unlike with the .AS and .DA directives.

Multiple expressions or strings should be separated by commas.

I have also included the .DW directive to improve the compatibility of word definitions with other assemblers.

Examples:

0000-78                    .DB   $12345678         Only the LSB is used
0001-7C                    .DB   5+$80-%1001       Complex expression
0002-12 34                 .DB   $12,$34           Multiple expressions
0004-54 65 73 74           .DB   "Test"            Only a string
0008-54 65 73 74
000C-0D 0A                 .DB   'Test',$0D,$0A    A string followed by 2 bytes
.DL    Data Long words

Syntax:

        .DL  [#¦/¦=¦\]expression[,[#¦/¦=¦\]expression[,...]]

See also: .AS .AT .AZ .DA .DB .DR .DW .HS .RF

Function:

The .DL directive is used to enter words and long words of data in the target code. The data is entered as one or more expressions, separated by commas.

Explanation:

Every expression following the .DL directive will be evaluated and a 16 bit word or the entire 32 bit long word is stored in the target file. The order in which the bytes are stored depends on the loaded Cross-Overlay. Some processors prefer to have the lowest byte stored first, others want the highest byte stored first. So please refer to the description of the particular Cross-Overlay to see in what order the bytes are stored.
The default order, when no Cross-Overlay is loaded, is lowest byte first. This is also known as little endian model.

The .DL directive is usually used to store long words of data, containing 4 bytes each. It can also be used to store words containing 2 bytes each. To store words the expression must be preceded by one of the symbols:

# stores the lowest word of the 32 bit result (b0..b15)
/ stores the middle 2 bytes (b8..b23)
= stores the highest word (b16..b31)
\ stores the highest byte (b24..b31), the upper 8 bits of the word remain 0

The long word of 4 bytes is stored if none of these prefixes is used.

Long words and words can be mixed together in the same .DL directive. Multiple expressions should be separated by commas.

Important: Be sure to load the appropriate Cross-Overlay before using the .DL directive! Otherwise the first data words may be saved in the wrong order (wrong endian model).

Unlike the .DA directive the .DL directive has no reverse endian model equivalent. If you want to store long words in the reverse order you should save the bytes or words separately by using the .DA or .DR directives.

Examples:

0000-78 56 34 12        .DL    $12345678
0004-78 56              .DL    #$12345678
0006-56 34              .DL    /$12345678
0008-34 12              .DL    =$12345678
000A-12 00              .DL    \$12345678
000C-78 56 34 12 
0010-78 56              .DL    $12345678,#$12345678
.DO    DO if condition is true

Syntax:

        .DO  expression

See also: .EL .EM .FI .MA .XM

Function:

The .DO directive is one of the 3 directives used for conditional assembly. It can be used to include or exclude parts of the source code from the assembly processes depending on a test condition.

Explanation:

If the expression evaluates to true (if its value is not 0) all following source lines will be assembled normally. If the expression evaluates to false (if its value is 0) the following source lines will not be assembled until the next .EL or .FI directive.

The .FI directive will end the conditional block that was started by the .DO directive, regardless of whether the expression evaluated to true or false.
The true/false condition can be reversed by the .EL directive as often as necessary.

The .DO .EL and .FI directives can be compared with IF, ELSE and ENDIF in other languages. Remember that the conditional directives control the assembler and not the target processor! They can not be used to let the target system compare values or make other decisions. The target system is unaware of the conditions used during assembly.

The expression must evaluate completely and may not contain any forward referenced labels. The .DO directive insists on knowing the condition and that is not possible if one of the labels is not defined yet.

Conditional assembly can be nested. This means that a .DO .FI block may contain other .DO .FI blocks. This nesting may go on, up to 255 levels deep. If that should not be enough for your application I suggest you get your head examined.

The listing of conditionally excluded source lines can be controlled with the .LI directive. If the .LI CON mode is selected all source lines are listed, regardless of the condition. Lines that are not assembled are marked with the word SKIP in the line number column. If the .LI COFF mode is selected the skipped lines are not listed at all.

Examples:

          .CR  Z80            Load the Z80 Cross-Overlay
          .DO  VALUE1>VALUE2
;                             These lines are assembled if
;                              VALUE1 is greater than VALUE 2
          NOP
          .EL                 Reverse condition
;                             These lines are not assembled
;                              if VALUE1 is greater than
;                              VALUE2
          NOP
          .FI                 End of conditional block

          .DO  VALUE1>VALUE2
          .DO  ?=0
;                             Condition nested 2 levels deep
;                             These lines are assembled if
;                              VALUE1 is greater than VALUE2
;                              and if we are in pass 1 of the
;                              assembly process (?)
          .FI                 End of 2nd condition (pass 1)
;                             These lines are assembled if
;                              VALUE1 is greater than VALUE2,
;                              regardless of the pass we're in.
          .FI                 First conditional is ended

          .DO  0              Condition is never true!
;                             This line will never be
;                              assembled
          .DO  1              This .DO is not evaluated
;                             This line is never assembled
;                             The value of the expression
;                              doesn't matter for the .DO
;                              is not evaluated anyway.
          .FI                 Nested .DO block ended
;                             This line is still not assembled
          .FI                 Closing outer .DO block
;                             This line is assembled again
.DR    Data Reverse

Syntax:

        .DR  [#¦/¦=¦\]expression[,[#¦/¦=¦\]expression[,...]]

See also: .AS .AT .AZ .DA .DB .DL .DW .HS .RF

Function:

The .DR directive is an alternative tool to enter bytes and words of data in the target code. The data is entered as one or more expressions, separated by commas.
It functions much the same as the .DA directive. The only difference is the order in which the bytes of a 16 bit value are stored.

Explanation:

Every expression following the .DR directive will be evaluated and the lower 16 bit value of the result is stored in the target file. The order in which the bytes are stored depends on the loaded Cross-Overlay. The order is opposite to the order in which the .DA directive would store the bytes of a 16 bit value. Therefore the order also depends on the loaded Cross-Overlay.
The default order, when no Cross-Overlay is loaded, is highest byte first. This is also known as big endian model.

The .DR directive can also be used to store single bytes in the target file. To store single bytes the expression must be preceded by one of the symbols:

# stores the lowest byte of the 32 bit result (b0..b7)
/ stores the 2nd lowest byte (b8..b15)
= stores the 2nd highest byte (b16..b23)
\ stores the highest byte (b24..b31)

Please note that there is no difference with the .DA directive when it comes to handling single bytes.

Data bytes and words can be mixed together in the same .DR directive. Multiple expressions should be separated by commas.

Important: Be sure to load the appropriate Cross-Overlay before using the .DR directive! Otherwise the first data words may be saved in the wrong order (wrong endian model).

Examples:

0000-09 53 7B 23
0004-61 E1                .DR     #%1001,#@123,#123,#$123,#'a',#"a"
0006-78                   .DR     #$12345678
0007-56                   .DR     /$12345678
0008-34                   .DR     =$12345678
0009-12                   .DR     \$12345678
000A-12 34                .DR     $1234             Notice the byte order
000C-7C                   .DR     #5+$80-%1001
000D-12 34 56             .DR     $1234,#$56        Mixed words and bytes
.DU    DUmmy mode

Syntax:

        .DU   [expression]

See also: .BS .ED .EP .NO .OR .PH .RF

Function:

The .DU directive is mainly used for defining RAM memory locations. Only the location is important while defining Labels in RAM area.

Explanation:

Code generated after the .DU directive is simply discarded. No code is saved to the target file what so ever. For the rest nothing has changed in the assembly process. Labels are assigned and addresses are counted as if the code really was saved.

Warning: Use the .DU directive with care. Wrong use of the .DU directive can create a program that will never work. The SB-Assembler won't warn you if you use the .DU directive in the wrong way.

The dummy block that is started by the .DU directive ends at the next .ED directive, or when a new dummy block is started. Also the .OR directive will end the current dummy block. However the .NO directive will not end the dummy block!

Everything on the source line following the .DU directive will be treated as comments.

Please note that the target address after .ED will be exactly equal to the target address at the time the .DU directive was given. Even though the current program counter has increased. Therefore the program counter and target address won't be in sync anymore.
This means that a new .OR directive should follow the .ED under most circumstances, at least if you intend to create a working program.

The dummy mode can span across multiple include files.

As from software version 2.07 you may also specify the starting address of the dummy block by using the optional expression. Effectively this combines a line with the .OR directive and a line with the .DU directive.
The expression must follow within 9 spaces from the .DU directive, otherwise it is treated as a comment field. The expression may not contain any forward referenced labels.

Examples:

           .OR    $8000        Start defining RAM area
           .DU                 But don't save the code anywhere
COUNTER    .BS    2            Define a 2 byte location
POINTER    .BS    2            Define another 2 byte location
FLAG       .BS    1            Define a single byte location
BUFFER     .BS    10           Define a 10 byte long buffer
VALUE      .BS    2            Define a 2 byte location
           .ED                 End of RAM definition

           .OR    $0000        The real program starts here

As from software version 2.07 this example may also be written as:

           .DU    $8000        Start defining RAM area
COUNTER    .BS    2            Define a 2 byte location
POINTER    .BS    2            Define another 2 byte location
FLAG       .BS    1            Define a single byte location
BUFFER     .BS    10           Define a 10 byte long buffer
VALUE      .BS    2            Define a 2 byte location
           .ED                 End of RAM definition

           .OR    $0000        The real program starts here
.DW    Define Word

Syntax:

        .DW  [expression[,[expression[,...]]

See also: .AS .AT .AZ .DA .DB .DL .DR .HS .RF

Function:

The .DW directive is used to enter words only and is meant to add some compatibility with other assemblers in the market. Operation of the .DW directive is almost the same as the DW directive found in most assemblers. Personally I prefer the use of the more powerful .DA directive.
Porting existing software to the SB-Assembler will become a little easier with this directive.

Explanation:

Every expression following the .DW directive will be evaluated and only the lower 16 bit value of the result is stored in the target file. The order in which the bytes are stored depends on the loaded Cross-Overlay. Some processors prefer to have the lowest byte stored first, others want the highest byte stored first. So please refer to the description of the particular Cross-Overlay to see in what order the bytes are stored.
The default order, when no Cross-Overlay is loaded, is lowest byte first. This is also known as little endian model.

Multiple expressions should be separated by commas.

Important: Be sure to load the appropriate Cross-Overlay before using the .DW directive! Otherwise the first data words may be saved in the wrong order (wrong endian model).

I have included the .DB directive to improve the compatibility of byte definitions with other assemblers too.

Examples:

0000-34 12               .DW   $1234           Notice the byte order
0002-7C 00               .DW   5+$80-%1001     A more complex expression
0004-34 12 78 56         .DW   $1234,$5678     Multiple expressions
.EB    Error Bell

Syntax:

        .EB  on¦off

See also: .CO .EC .EN .ER .ST

Function:

With this directive you can turn the Error Bell on or off. The Error Bell is the beep that is generated every time the SB-Assembler stumbles over an error in your source code.

Explanation:

Per default the Error Bell option is switched on, which sounds a beep for every error in your source code.

Examples:

         .EB   ON          Switch Error Bell option on
         .EB   OFF         Switch Error Bell option off
.EC    End Comment

Syntax:

        .EC

See also: .CO .EB .EN .ER .ST

Function:

This directive ends the comment block that was started by the .CO directive. Provided that the label field of the source line is empty and the .EC directive appears in the instruction field. Otherwise the comment block is not ended.

Explanation:

The label field should be empty and the .EC directive must appear in the instruction field to make it effective. Otherwise the comment block won't be terminated. This means that at least one space or TAB character must precede the .EC directive. No other characters are allowed before the .EC directive, otherwise it will simply be part of the comment lines.

Everything on the same source line that follows the .EC directive will still be treated as comment.

An error message will be reported if the comment block was not activated.

.ED    End Dummy mode

Syntax:

        .ED

See also: .BS .DU .EP .NO .OR .PH .RF

Function:

The .ED directive will end the dummy mode that was started by the .DU directive.

Explanation:

No error is reported if the dummy mode was not started when the .ED directive is encountered. In that case the .ED directive will simply be ignored.

Everything on the source line following the .ED directive will be treated as comment.

The SB-Assembler will not warn you if the program ends when no .ED directive ended an active dummy mode. The dummy mode can span across multiple include files.

.EF    Error File

Syntax:

        .EF  filename[.ext]

See also: .CP .EJ .LF .LI .LM .PG .SF .TF .TI .TW

Function:

The .EF directive allows you to send all reported assembling errors to a specific file or device. Opening this file will allow you to quickly locate the locations in your source files which contain the errors.

Explanation:

The SB-Assembler will send all reported errors to the file that was opened with the .EF directive. Apart from this the errors will still be sent to the normal list file and screen if the listing is switched on. Errors will always be displayed on the screen and logged in an opened error file, regardless of the selected list options.
The errors reported in the error file are labelled with the originating source file name and the line number in which the error occurred. This allows you to quickly locate the affected source lines.
The error file remains empty if no errors are reported during the assembling process.

If the error file does not exist yet it will be created. If a file with the same name already exists in the given path it will be overwritten without prior notice.

If you want to make use of the .EF directive you should place that directive preferably in the first few lines of the main source file, before potential errors may occur. Otherwise some errors may not be logged.
Only one error file can be created in one assembly run. That error file can not be closed until the end of the assembling process, at which point the SB-Assembler will close all files it had opened.
The error file will be opened during the first pass of the assembling processes. This allows logging of errors that occur in the first pass as well.

As usual, the filename may be preceded by drive letter and path. If no extension .ext is given the SB-Assembler assumes the default extension for error files, which is .ERR.
It is also possible to send error messages to a device like a printer for instance. In that case the device name should end in a colon.

Examples:

            .EF  ERRORS              The errors are sent to the
;                                     file ERRORS.ERR

            .EF  LPT1:               The errors are sent to the
;                                     first printer (mind the : )

            .EF  C:\TEXT\ERRORS.PRN  The errors are sent to
;                                      the file ERRORS.PRN on
;                                      drive C:\TEXT

Please note that these are 3 separate examples which may not be used together in one single source.

.EJ    EJect

Syntax:

        .EJ

See also: .CP .EF .LF .LI .LM .PG .SF .TF .TI .TW

Function:

The .EJ directive sends a Form Feed character to the list file. When sending the listing to the printer this will cause ejecting of the current page. At the same time the line counter for the list file is reset to 0 and the page number is incremented.
This directive will only work during the second pass of the assembly process because the SB-Assembler does not list anything at all during the first pass (apart from error messages).

Explanation:

This directive acts like the .PG directive. The only difference is that .EJ will not print a new page head above the new page like .PG does.

The source line containing the .EJ directive will not be listed in the list file. Everything following .EJ on the source line will be treated as comment.

If the listing is set to Single Sheet mode by the .TI directive the assembly process will come to a halt and a message is put on the screen requesting you to insert a new page. Hit any key when a new page is inserted to continue the assembly process.

.EL    ELse condition

Syntax:

        .EL

See also: .DO .EM .FI .MA .XM

Function:

The .EL directive is used together with the conditional assembly directives .DO and .FI. The .EL directive will invert the current condition.

Explanation:

The .EL directive inverts the current test condition. If the current condition was true it will become false. And if it was false it will become true. The following program lines are only assembled if the condition is true until the next .EL directive or until the .FI directive is encountered.

The .EL directive may be used as often as you want to invert the condition between the .DO and .FI directives. The condition is inverted every time the .EL directive is used.

The label field of the source line on which the .EL directive is used must be empty. So it's not possible to declare a label on a source line that contains the .EL directive.

Examples:

           .DO  1            Condition is always true (<>0)
;                            These lines are interpreted by
;                             the SB-Assembler
           .EL               Reverse condition
;                            This line is not interpreted
           .EL               Reverse condition
;                            This line is again interpreted
           .EL               Reverse condition
;                            This line is again not interpreted
           .FI               End of conditional block
.EM    End Macro definition

Syntax:

        .EM

See also: Macros .DO .EL .FI .MA .XM

Function:

This directive ends a Macro definition that was started by the .MA directive unconditionally.
Macro operation is explained in more detail in a separate chapter.

Explanation:

The label field of the source line containing the .EM directive should be empty. It is not possible to define a label on the same line.
Everything on the source line following the .EM directive will be ignored.

.EN    ENd

Syntax:

        .EN

See also: .CO .EB .EC .ER .ST

Function:

This directive signals the end of the current source file. The source line containing the .EN directive will be the last line that is assembled of the current source file, regardless of what ever follows it. The current source file is closed and in case it was an include file the SB-Assembler will continue to process the main source file as if the include file was ended in a natural way.
With the SB-Assembler the use of the .EN directive is completely optional. Unlike some other assemblers the SB-Assembler is clever enough to detect the natural end of the source file.

Explanation:

The .EN directive can be used to end a source file prematurely. This could be useful for debugging purposes or if the rest of the source file contains only comments which don't have to be listed in the list file.
The source line containing the .EN directive is always the last line that is assembled of the current source file. The file is immediately closed and all text following the current source line will be ignored completely.

If the .EN directive is encountered in the main source file assembly will stop immediately. If we were still in pass 1 the assembler will start pass 2 of the assembly process.
If the .EN directive is encountered in an include file then that file will be closed and the assembler continues with the main source file as if the included file had reached its natural end.

.EP    End Patch

Syntax:

        .EP

See also: .BS .DU .ED .NO .OR .PH .RF

Function:

With the .EP directive the so called patch mode, that was started by the .PH directive, is switched off .

Explanation:

The .EP directive switches off the so-called patch mode. This effectively means that the program counter gets the same value as the target pointer again.
The .EP directive will be ignored if the patch mode was not activated. The program counter and target address were already in sync with each other.

A possible label in the label field of the source line still gets the value of the last patch address.

Everything on the source line following the .EP directive is ignored and therefore will be treated as comment.

Please refer to the .PH directive for more details about the patch mode.

.EQ    EQuate

Syntax:

label     .EQ    expression
label     =      expression

See also: .SE

Function:

The .EQ directive is used to assign a value other than the default program counter value to a label. Alternatively the = symbol may be used instead of the .EQ directive.

Explanation:

The .EQ directive is used to assign a constant value to a label. Per default a new label will get the value of the current program counter. If you want the new label to get a different value than its default value you should use the .EQ directive. The = symbol is equivalent to the .EQ directive and has exactly the same effect.

A label that was assigned using the .EQ directive can be considered a constant value because its value can not be changed anymore.
Internally the label value is always 32 bits long. The expression may not be preceded by the # / = and \ symbols to force the value to be only 8 bits in length.

Please note that the .EQ directive does not generate any code for the target system. It only assigns the expression's value to a label which helps us humans to cope better with meaningless numbers.

Forward referenced labels in the expression are not allowed. This means that all labels in the expression should be completely resolved.

The SB-Assembler will stop parsing the source line immediately after it has evaluated the expression. Everything following the expression is treated as a comment. This will allow you to let the expression be followed by a second expression to indicate that the label's value is the beginning of multiple addresses. It will have no effect on the value that is assigned to the label though.

Like all labels used with the SB-Assembler, labels declared with the .EQ directive may be redefined, as long as the new definition gives the label the same value as it already had. This is useful if labels are declared in libraries. Linking multiple libraries may cause some labels to be redefined. This is no problem as long as the definition results in the same value every time. For this redefinition it doesn't matter whether the label gets its value automatically or by using the .EQ directive.
The SB-Assembler will report an "Extra definition error" if a label is redefined with a different value than the first time.

It is even allowed to assign a value to Local labels using the .EQ directive. The SB-Assembler won't protest if you do. But remember that Local labels only "live" until the definition of the next Global label.

Legal Examples:

1234-       LABEL     .EQ    $1234        Assign a constant value to LABEL
000D-       CR        .EQ    $0D          Assign the Carriage Return to CR
0050-       POINTER   .EQ    $50,$51      Assign the value $50 to POINTER,
0000-       ;                              the rest is treated as comment
1236-       NEW       .EQ    LABEL+2      LABEL is already defined
ABCD-       ALT       =      $ABCD        = symbol is equivalent to .EQ
123456-     BIG       .EQ    $123456      Number larger than 16-bits
12345678-   VERYBIG   .EQ    $12345678    And even larger (up to 32 bits)

Illegal Examples:

            TEST      .EQ    FORWARD      Forward referenced!
            ERROR     .EQ    #$0D         # prefix not allowed here
                      .EQ    %1001        Label field is empty
            MISSING   .EQ                 ; The expression is missing
.ER    forced ERror

Syntax:

        .ER  [F[,]][errormessage]

See also: .DO .EL .FI .CO .EB .EC .EN .ST

Function:

The .ER directive can force the SB-Assembler to report an error message. Such an error message can either be a normal error or a fatal error.

Example:

You can force an error message to be reported with the use of the .ER directive. This may be useful if you want to be warned if the program you're writing exceeds a certain memory range, or if a memory page boundary is crossed.
The .ER directive is intended to be used in co-operation with the conditional assembly directives .DO .EL and .FI. Without conditional assembly this directive has very little use because the SB-Assembler would never reach pass 2 to produce the program if the .ER directive is used unconditionally.

The parameter following the .ER directive is the text of the error message that is reported. It is not possible to place comments on the same source line. All text is considered to be the error message, including spaces. Even the case of the characters of the message is retained. The parameter doesn't have to be enclosed in delimiters, like it would have been for other literal strings.

If no parameter is given the standard text "*** User error" is reported.

If the parameter is a single character F or an F followed by a comma a fatal error will be reported. A fatal error will terminate the assembly process immediately.
If you want to include a custom error text with this fatal error the character F must be followed by a comma, which should be followed by the custom error message.

Examples:

; Generate a standard non-fatal error
         .ER

; Generate a standard fatal error
         .ER   F

; Generate a custom non-fatal error
         .ER   *** This is the error message

; Generate a custom fatal error
         .ER   F,*** This is the error message
.FI    FInished conditional

Syntax:

        .FI

See also: .DO .EL .EM .MA .XM

Function:

The .FI directive is used in co-operation with .DO and .EL for conditional assembly. The .FI directive will close a condition that was opened by the last .DO directive.

Explanation:

The .FI directive will close the condition that was opened by the last .DO directive and at the same time it will decrement the nesting counter.
The conditional mode will be terminated if the nesting counter reaches 0. In that case all following source lines will be assembled unconditionally.
The SB-Assembler will report a "Missing .DO error" if no .DO is active. This is when the nesting counter was already 0 when the .FI directive is encountered.

The label field of the source line containing the .FI directive must be empty. So it's not possible to declare a label on a source line that contains the .FI directive.

Examples:

         .DO  1         Condition always true (<>0)
;                       This line is assembled
         .EL            Reverse condition
;                       This line will not be assembled
         .FI            End of conditional assembly
;                       This line and following lines
;                       are assembled unconditionally.
.HS    Hex String

Syntax:

        .HS  [.]hexbyte[,[.]hexbyte[,.....]]

See also: .AS .AT .AZ .DA .DB .DL .DR .DW .RF

Function:

The .HS directive accepts a string of hexadecimal encoded bytes. Each hexadecimal encoded byte must consist of 2 hexadecimal digits.
The .HS directive can be used to enter large tables of hexadecimal bytes with less parameter overhead than with the normal .DA directive.

Explanation:

The Hex String consists of a number of hexadecimal digit pairs. Every digit pair may be separated from the next pair with a dot. This dot serves no purpose other than improving the readability for us humans. Digit pairs belonging to the same byte may not be separated by a dot!
Bytes should be entered as a digit pair, which means that leading zeroes must be included!

The bytes are saved to the target file in the order of appearance.

All data entered are plain hexadecimal bytes. No expressions are allowed here.
The interpretation of the Hex String is ended at the first space, TAB or EOL. The rest of the line is regarded as comment.

Examples:

0000-01 23 45 67
0004-89 AB CD EF            .HS   .01.23.45.67.89.AB.CD.EF
0008-01 23 45 67
000C-89 AB CD EF            .HS   0123456789ABCDEF
0010-01 23 45 67
0014-89 AB CD EF            .HS   0123.4567.89AB.CDEF
.IN    INclude source file

Syntax:

        .IN  filename[.ext]

See also: .BI .CH

Function:

The .IN directive allows you to split the complete source text of your program into different modules.

Explanation:

Splitting a large job into smaller sub-jobs makes program management and total overview a lot easier. This is also true for creating programs in assembly. The maximum source file size the SB-Assembler can handle is only limited by your favourite text editor. However shorter files, each dedicated to a specific task, are much easier to maintain.

The main source file is opened when you start the SB-Assembler. This main source file may open as many include files as you like. Preferably the main source file should only contain some initialization directives like .CR and .OR and all necessary .INclude files.

The .IN directive requires a filename as parameter. This filename may be preceded by a drive letter and path name. The extension .ext is optional. If the extension is omitted the default extension .ASM is used.
The maximum total length of path and file name may not exceed 122 characters.

An include file will be closed when the assembler reaches the end of the include file. Assembly will then continue in the main source file on the line following the line that opened the include file.
Please notice that all include files are opened and closed twice during the 2 pass assembly process.

It is not possible to nest include files. This means that you can not open another include file from within an include file.

Line numbers in list files are preceded with an 'I' to indicate that they stem from an include file. Line numbers are reset to 1 every time a new include file is opened.

Examples:

        .IN  DECLARE            Include declaration module

        .IN  C:\LIB\MACRO.LIB   Include Macro library

        .IN  INIT               Include initialization module
.LF    List File

Syntax:

        .LF  [filename[.ext][,linelength]]

See also: .CP .EF .EJ .LI .LM .PG .SF .TF .TI .TW

Function:

With the .LF directive you can divert the listing output from the screen to a file or other output device.
During the assembly process you can divert the listing to different files or devices as often as you like. However only one diversion can be active at the same time.

Explanation:

Per default the listing is output to the screen with a maximum line length of 254 characters. This means that longer lines are simply broken down at the right end of the screen and continue on the next line.

The filename may be preceded by a drive letter and path name. If no extension .ext is given the default extension .LST is used. If you want to send the listing to a device the device name should be followed by a colon like in COM1: PRN: AUX: NUL:.

An already open list file will be closed when the .LF directive is given. If no filename is given the output will be redirected to the screen again.
If you want to add a comment on a line that should only contain an empty .LF directive this comment should be preceded with a semicolon, otherwise it is treated as a file name.

A new file will be created if the filename does not exist yet. If the filename does already exist its length is reduced to 0, effectively overwriting the existing file irreversible without prior warning.

The filename may be followed by the maximum line length to be used in the listing. A comma should separate the filename from the linelength expression.
Lines in the listing will be truncated at this maximum length. All other characters on such a line will be discarded in the listing. The minimum line length is 64 characters long. The maximum length is 254 characters, excluding the closing CR and LF characters.

Source lines containing the .LF directive will only be interpreted during pass 2 of the assembly process. Any errors in the parameters will be detected in pass 2.

Source lines containing the .LF directive will never be listed in a list file themselves.

Please note that you are still able to exclude parts of the program from being sent to the list file by using the .LI directive.

Examples:

         .LF  LIST         Send listing to LIST.LST
         .LF  C:\ASSEMBLE\TEST.PRN  Send listing to TEST.PRN
;                           on drive C: in directory \ASSEMBLE\
         .LF  LPT1:        Send listing to LPT1
         .LF  CON:         Send listings to the screen
         .LF  CON:,79      Send listing to screen, max length 79
         .LF  NUL:         Send listing to NUL device
         .LF             ; Close listing file, output to screen
.LI    LIst options

Syntax:

        .LI  on¦off¦mon¦moff¦con¦coff[,on¦off¦mon¦moff¦con¦coff[,.....]]

See also: .CP .EF .EJ .LF .LM .PG .SF .TF .TI .TW

Function:

With the .LI directive you can precisely control what is listed to the list file or screen during assembly.
For instance if you put the directive .LI OFF at the very last line of your source file you will inhibit the time consuming listing of the symbol table.

Explanation:

At least one list option should be present in the parameter field. Multiple list options should be separated by commas.

With the option on¦off you can switch the listing completely on or off. Nothing will be sent to the list file or screen if the listing is switched off. Please note that error messages will always be listed, regardless of the settings of the list options.
The off list option has priority over all other list option. If the list option is switched off there's nothing the other options can do about it.

With the mon¦moff option you can switch the listing of expanding Macros on or off. Expanding Macros will not be listed if this option is switched off. The line calling the Macro to expand will be listed however.
Please note that the listing of the definition of the Macro will not be affected by this list option.
If the Macro list option is switched on (mon) all following Macro expansions will be listed completely in the list file or to the screen. The letter M will precede all Macro line number in the list file.

With the con¦coff option you can control the listing of source lines that are not assembled due to a false condition.
Source lines that are not assembled because a previous condition proved to be false will not be listed if the coff list option is selected. Program lines that are assembled because of a true condition will be listed normally.
All source lines will be listed if the con list option is selected. So also the lines that are not assembled due to a false condition will be listed. Source lines that are not assembled due to a false condition will be marked with the word SKIP in the line number column of the list file.

Per default all three list options are switched on. This means that all source lines will be sent to the list file or screen.

It is allowed to have multiple list options in the parameter field after the .LI directive, as long as they are separated from each other by commas. It is even allowed to switch any of the list options on and off repeatedly on the same line, although only the last option will be remembered.
For example the next source line will switch the main and conditional list options on, and the Macro list option off.

         .LI  OFF,MON,COFF,ON,CON,MOFF

Source lines containing a .LI directive will never be listed in the list file them selves. Except when an error in such a line is detected.

Examples:

         .LI   ON              Switch main list option on
         .LI   OFF             Switch main list option off
         .LI   MON             Switch macro list option on
         .LI   MOFF            Switch macro list option off
         .LI   CON             Switch conditional list option on
         .LI   COFF            Switch conditional list option off
         .LI   ON,MON,CON      Switch all options on
         .LI   OFF,MOFF,COFF   Switch all options off
         .LI   ON,MOFF,CON     Only macro option off
         .LI   ON,OFF,ON,OFF   Results in main list option on
.LM    Left Margin

Syntax:

        .LM  expression

See also: .CP .EF .EJ .LF .LI .PG .SF .TF .TI .TW

Function:

With the .LM directive you can set the width of the left margin of the list file. This is useful if you plan to send the listing to a printer.

Explanation:

Usually the lines of a list file begin in the left most column. With the .LM directive you can let each line begin with a number of spaces to create a left margin. The number of spaces used as a margin is determined by the expression that follows the .LM directive. The expression may have a value in the range from 0 to 16. The expression may not contain forward referenced labels.
The setting of the left margin has no effect if the listing is sent to the screen.

The .LM directive will only be evaluated during pass 2 of the assembly process. Any errors in the parameter will be detected in pass 2.

.MA    MAcro definition

Syntax:

macroname    .MA    [comment]
             .MA    macroname [comment]

See also: Macros .DO .EL .EM .FI .XM

Function:

The .MA directive starts the definition of a Macro.

Explanation:

The syntax of the .MA directive has 2 appearances.
The first one above has the more usual notation with the macroname in the label field, followed by the .MA directive in the instruction field. The .MA directive may be followed by comments.
The second notation puts the macroname in the operand field, behind the .MA directive. This notation is not recommended and is only available for compatibility reasons with the Apple ][ version of the SB-Assembler. The macroname may also be followed by comments in this notation.

There is a special reason why I explicitly say that comments are allowed behind the .MA directive. Most directives may be followed by comments, so that's not so special by itself. But here it is particularly useful to add comments to indicate what parameters are expected by the Macro that you're going to define.
Please note that the real parameters are given at the instances where you want the Macro to expand. Here, after the .MA directive they serve only a documentary purpose.

The same rules as for Global label names apply to macroname, with the only exception that a macroname is only remembered up to 31 characters. The macroname must start with a character from A to Z, an may contain other characters from A to Z, digits from 0 to 9, the underscore _ and a dot .
The macroname must be a unique Macro name. However it is allowed to give a Macro the same name as a label. Macro names are stored separately in the symbol table.

The following directives are not allowed during the definition of a Macro (from the opening .MA directive until the closing .EM directive):

.MA, .IN, .CH, .BI, .EN, .CO and .EC

New Local label definitions are not allowed after a Macro definition until at least one new Global label is declared.

A fatal error will be reported if the end of a source file is reached while in the middle of defining a Macro with the .MA directive.

A detailed description of the Macro capabilities of the SB-Assembler can be found in a separate chapter.

Examples:

Let's define a Macro that exchanges 2 bytes in memory without altering any of the processor's registers on a 6502.

XCHNG    .MA  memory1,memory2
         PHP           ; Save flags register
         PHA           ; Save Accu
         LDA  ]1       ; Get the 1st byte from memory
         PHA           ;  and put it on the stack
         LDA  ]2       ; Copy the 2nd byte to the
         STA  ]1       ;  1st memory location
         PLA           ; Save the 1st byte to 
         STA  ]2       ;  the 2nd memory location
         PLA           ; Restore Accu
         PLP           ; Restore the flags register
         .EM           ; Done

Please note that I deliberately included the semicolon in the comment field. Usually this semicolon is optional in the SB-Assembler. But during a Macro definition it prohibits the comments from being saved to the symbol table. You can simply omit the use of the semicolon if you want the comments to be repeated every time you expand the Macro at the penalty of using more space in the symbol table.
All parameters in the Macro definition have the notation ]x , where x is the parameter number. This parameter number is determined by the location in the operand field of the Macro call. In the example above the parameter ]1 will be replaced by the first parameter memory1. The parameter ]2 will be replaced by the second parameter memory2.

.NO    New Origin

Syntax:

        .NO  expression1[,expression2]

See also: .BS .DU .ED .EP .OR .PH .RF

Function:

The .NO directive is very similar to the .OR directive, yet has some significant differences.

Explanation:

The effect of this directive is that the program counter is set to the value of expression1. The way that this is done differs significantly from the way the .OR directive would do that. In principle the .NO directive works identical to the .BS directive, with the only difference being the way the block size is defined. With the .BS directive you say how big the skipped block should be in terms of the number of bytes. The .NO directive expects you to specify where the skipped block will end by providing the end address in expression1.

Expression1 may not contain forward referenced labels otherwise a fatal "Undefined label error" will be reported.

The two following program lines will have exactly the same effect:

         .NO  newpc
         .BS  newpc-$

You can determine what should be done with the skipped bytes by supplying the fill value in expression2, just like with the .BS directive.

The value of expression1 may not be less than the current program counter. Values less than the current program counter would otherwise result in very large blocks to be skipped.
The maximum value of expression2 is $FF. Larger values will simply be truncated at the lowest byte before they are used. A value of $100 will fill the skipped memory with the value of $00.

Operation of the .NO directive differs a little between formatted and unformatted target files.
With unformatted target files a filling value is always used, whether expression2 is given or not. If expression2 is omitted the value $00 is used to fill the skipped memory.
With formatted target files a filling value is only used if expression2 is given. Otherwise the skipped memory block will be skipped completely. The current data record will be terminated and a new one is started with the new target address in the address field.
The only exception to this rule is when the number of bytes skipped is less than the line record length of the target file. In that case bytes with the value of $00 are used to fill the skipped memory.

The list file will only contain the first address of the skipped memory block. The filled bytes are not listed in the list file.

Please note that unformatted files rely on the .NO directive to change the program counter because using the .OR directive would close an unformatted file immediately.

Examples:

This is a typical 6502 program to be burned into EPROM. First comes the program together with interrupt routines. Interrupt and reset vectors must be placed at the end of the address space.

         .OR    $F800        Start address of the ROM
NMI      NOP                 The NMI routine
          ;
          ;
          ;
         RTI

IRQ      NOP                 The interrupt request routine
          ;
          ;
          ;
         RTI

RESET    NOP                 The initialization routine
          ;
          ;
          ;
         JMP    AGAIN        End of the program

         .NO    $FFFA,$FF    Skip all unused memory until
;                             the vector space. All skipped
;                             bytes are filled with $FF
         .DA    NMI          The NMI vector
         .DA    RESET        The Reset vector
         .DA    IRQ          The IRQ vector
.OR    ORigin

Syntax:

    .OR  expression

See also: .BS .DU .ED .EP .NO .PH .RF

Function:

The .OR directive is used to set the starting address of a program, a part of the program, or a data block. All following bytes are stored in consecutive addresses, starting at the address specified by expression.

Explanation:

The .OR directive sets both the program counter and target address to the value of the expression.
This effectively switches off a possible patch mode (see .PH directive). A possible dummy mode is also terminated (see .DU directive).

The expression may not contain forward referenced labels otherwise a fatal "Undefined label error" will be reported.

One single assemble run may contain several .OR directives. But some additional rules exist when sending the generated code to an unformatted target file like BIN or HEX.
The .OR directive will close an unformatted target file because these file formats do not support address information. Formatted files do support address information and those files will not be closed by the .OR directive. This implies that you have to use the .OR directive before creating an unformatted file, otherwise you'll end up with an empty target file.
If you do use more than one .OR directive together with unformatted files you'll have to open a new target file every time the .OR directive is used. Therefore you should better use the .NO directive when you're using unformatted target files.
The occurrence of the .OR directive while using formatted files will flush the current target line buffer to the target file and a new target line is started with the new address in the address field.

Due to several questions from users I decided to change (read: improve) the behaviour of the .OR directive in combination with unformatted files. As from software version 2.07 it is now allowed to start an unformatted file before setting the .OR address, but only if the unformatted file is still empty. However if the .OR directive is used when the unformatted file is not empty it will still close the target file, there is no way to prevent that!

It goes without saying that the programmer is responsible to prevent overlapping of memory spaces when multiple .OR directives are used in one assembly run. The SB-Assembler will not protest if you reset the target address to an already used location of memory.
When writing a program that has to run in bank switched memory you better use the .PH directive instead of using the .OR directive to reset the program counter every time you want to start again from the beginning of the bank switched memory area.
If you insist on using the .OR directive for bank switched memory applications you should store every overlay in a separate target file.

Examples:

         .OR   $1000    Store program from $1000 upwards
          ;
          ;
          ;

         .OR   $2000    Continue from address $2000
          ;
          ;
          ;

         .OR   $0000    You can also continue at lower addresses
          ;
          ;
          ;
.PG    PaGe

Syntax:

        .PG  [expression]

See also: .CP .EF .EJ .LF .LI .LM .SF .TF .TI .TW

Function:

The .PG directive will force the listing to start on a new page in the list file or list device. The title, set by the .TI directive, will be printed on top of that new page along with the page number. The printing of the title and page number on top of the new page is the only difference with the .EJ directive.

Explanation:

If a title is defined by a .TI directive it will be printed on the first line of the new page, along with the page number.

If expression is given the new page will be numbered with the value of the expression. The expression should not be more than 9 spaces away from the .PG directive to be evaluated, otherwise it will be treated as a comment.
The high word of the expression's value will not be included in the page number and is assumed to be 0. The largest page number that can be used is 65535, which should be more than sufficient I think.

A source line containing the .PG directive will never be listed in the list file itself, unless an error is encountered on that line.
A source line containing the .PG directive will only be evaluated in the second pass of the assembly process.

.PH    PatcH

Syntax:

        .PH  expression

See also: .BS .DU .ED .EP .NO .OR .RF

Function:

The .PH directive will switch over to the patch mode. The current program counter is saved during patch mode. The saved program counter will still count up for every byte that is saved to the target file in the background. At the same time a new, temporary, program counter is selected. The .EP directive switches of the patch mode and replaces the temporary program counter with the original one again.

Explanation:

The expression may not contain forward referenced labels otherwise a fatal "Undefined label error" will be reported.

A possible patch mode will be automatically closed when a new patch mode is initiated. This allows you to write multiple patch routines in a row, where each patch routine gets its own address space.

Please note that the .OR directive also terminates an active patch mode automatically.

The patch mode is typically used to generate pieces of code that are moved to a different memory location by the processor before it is used as code. All labels that are defined during the patch mode automatically get the appropriate values as if the code really was generated at the intended address. In the mean time the code is saved to the target file in a consecutive order as if the program counter was not changed.

Originally the patch mode was intended to write some patch routines that should be copied into an existing program by a simple move routine, hence it's name.

Another useful application for the patch mode is writing code that is supposed to start at e.g. address $8000 of the target system, but should be burned to an EPROM starting at address $0000. You can't simply use .OR $0000 because that would produce erratic destination addresses for jumps, calls and memory access instructions.
The patch mode can solve this little dilemma by setting .OR $0000 and then .PH $8000. Code will be saved to the target file starting at address $0000. But the SB-Assembler pretends to generate code that originates at address $8000.

The patch mode can also be used to write programs that should run in bank switched memory.
Imagine a system that has 4 banks of memory mapped in the address space from $0800 to $0FFF. The first time you can simply set the .OR to $0800. The code is sent to the target file starting at address $0800. But if you want to program the next memory block you can't use .OR $0800 again because that would effectively overwrite the code of the previous block of memory, which also started at $0800.
Example 2 explains how this can be solved by using the .PH directive.

Example 1:

Imagine a piece of 6502 program that should be copied to RAM memory to allow direct changing of addresses used by instructions.

8000-                   .OR  $8000         Begin of program
8000-A0 0A    INSTALL   LDY  #NEXT-PATCH1  Calc. length of patch
8002-B9 0C 80 .LOOP     LDA  PATCH,Y       Get byte from ROM
8005-99 00 20           STA  RAM,Y          and put it in RAM
8008-88                 DEY                Decrement length counter
8009-10 F7              BPL  .LOOP         Repeat while Y>=0
800B-60                 RTS
800C-
800C-         PATCH     .PH  $2000         Destination of patch routine
2000-48       RAM       PHA                Save Accu on stack
2001-AD 00 00           LDA  $0000         Address may be changed
;                                           dynamically because it's
;                                           stored in RAM now
2004-38       .LOOP     NOP                Any other code goes here
2005-68                 PLA                Restore Accu
2006-60                 RTS
2007-                   .EP                End of patch routine
8013-
8013-EA       NEXT      NOP                The rest of ROM code

Explanation: The INSTALL routine copies the patch routine to RAM location starting at address $2000. In this case the patch routine may not be longer than 127 bytes to simplify the copy loop. The first thing that's done is calculating the length of the routine that has to be moved by subtracting the end address of the patch routine in ROM ($8013) from the begin address of the patch routine in ROM ($800C, and not $2000!). Then the patch routine is copied to RAM byte by byte.
The labels defined in the patch routine get the value as if the routine was already copied to its RAM location. The label RAM gets the value of $2000 and the Local label .LOOP is assigned the value $2004. In reality however the object bytes of the patch routine generated by the assembler are stored in the normal sequence at the addresses $800C to $8012.

Example 2:

Imagine you want to create a program for the 8048 processor which can address only 4 kb of ROM memory. But you want to increase to ROM addressing range to 8 kb by using bank switching. The memory address $0000 to $07FF (2 kb) is always available. The memory from $0800 to $0FFF is available 3 times in 3 different banks. Two I/O lines control what bank is selected.

0000-            .OR  $000        Begin of bank 0
                  ;               Here come universal
                  ;                routines, the interrupt
                  ;                service routines and bank
                  ;                switch routines.
                 .NO  $800,$FF    Fill bank 0 with $FF

0800-            NOP               Bank 1.1 starts at $0800,
                  ;                No special attention is
                  ;                 required yet to do that.
                  ;                Here comes the code
                  ;                 of bank 1.1
                 .NO  $FFF,$FF     Fill bank 1.1 with $FF

1000-            .PH  $800         Bank 1.2 again starts at
0800-             ;                 address $0800. But this time
                  ;                 the target address in the
                  ;                 object file continues normally
                  ;                 from $1000 where we are now.
                  ;                Here comes the code of bank 1.2
                 .NO  $FFF,$FF     Fill bank 1.2 with $FF
1000-            .EP               (.EP is optional here)

1800-            .PH  $800         Bank 1.3 also starts at
0800-             ;                 address $0800. The target
                  ;                 address still continues which
                  ;                 is $1800 now.
                  ;                Here comes the code of bank 1.3
                 .NO  $FFF,$FF     Fill bank 1.3 with $FF
                 .EP               End of bank 1.3

Explanation: Bank 0 of the program is nothing special from the SB-Assembler's point of view. Bank 0 contains some universal routines, interrupt service routines and bank switch routines. Bank 0 is always available to the target processor.
Bank 1.1 is a normal bank 1 which can be coded as usual. The bank starts at address $0800, immediately following bank 0. The bank continues to address $0FFF. The .NO directive fills the unused portion of bank 1.1 with $FF.
Bank 1.2 should also start at address $0800, at least the 8048 must think it does. But the address space from $0800 to $0FFF is already used in the EPROM. But by using the .PH directive we can pretend to start at address $0800 again, while in reality the code continues to be stored from address $1000 onward.
The procedure for bank 1.3 is equal to that for bank 1.2, with the only difference being the target address in EPROM that has grown to $1800.

Please note that switching from bank 1.2 to bank 1.3 does not necessarily require the .EP directive. The .PH directive would have automatically executed an .EP directive.
The last bank does not have to be filled completely because there are no more banks following it. Also the last .EP is optional. It is allowed to end the program without ending the patch mode first.

This example works for formatted and unformatted target files because all banks are filled completely by using the .NO directives at the end of every bank.
It is also possible to use the .OR directive instead of the .NO directive to start the new bank. In that case we can't use unformatted files however.

.RF    Random Fill

Syntax:

          .RF  expression1,[expression2]

See also: .AS .AT .AZ .DA .DB .DL .DR .DW .HS

Function:

The .RF directive can fill a portion of memory with randomly generated bytes. This can be useful for software security.

Explanation:

The expression1 indicates the number of bytes that should be filled with randomly generated values. Expression1 may not contain any forward referenced labels.

The optional expression2 can be used as a seed value for the pseudo random number generator. If expression2 is not used the pseudo random bytes generated are different every time the source file is assembled. By specifying the seed you can generate the same pseudo random sequence time after time. The exact value of the seed is not important and may range from $0000 to $FFFF. Larger values will be truncated to 16 bit values.

The pseudo random sequence will repeat itself after 65536 generated bytes. This is not a big problem for I can't think of an application that would require more random bytes than that.

Examples:

For example the single chip processor 8051 (or its relatives) provide a few security levels to prevent software piracy. One of these levels of security encrypt the ROM contents when read by a programmer. Without the correct encryption key sequence this information is useless.
The encryption system of the 8051 uses a 32 byte encryption key. All bytes read are EXNORred with one of those key bytes. The keys are used in sequence over and over again. Now imagine that only 3 kb of the 4 kb program space is used in your 8051 system. That would leave an empty space of 1 kb in your ROM. If you don't put something in there all bytes from that empty space will read $FF. Using the encryption system will EXNOR all these $FF bytes with the encryption key sequence, resulting in exactly the encryption key sequence repeating over and over again every 32 bytes!
All a potential software pirate has to do is check to see if a 32 byte sequence repeats itself at the end of the program space to find out what your encryption key sequence is. Knowing the encryption key sequence he is now capable of decoding your program again.
Filling the unused portion of your ROM with randomly generated bytes can easily fill this security hole. I don't say that it will become impossible to break your code if you do, but you will make it a lot harder for the software pirate to obtain your life's work.

Examples:

         .RF  $1000-$     Fill up to 4kb with random numbers
.SE    SEt variable