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  

This page has not been adapted to SB-Assembler Version 3 yet.

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

Syntax:

label   .SE  expression

See also: .EQ

Function:

With the .SE directive you can declare and change a variable value to a label.

Explanation:

Normally only constant values are assigned to labels. Once a particular value is assigned to a label it can not be changed anymore.
The .SE directive allows you to declare a label with a variable value. You can change the value as often as you want. For example this may come in handy for counters, intermediate results and for complex expressions.

The syntax for the .SE directive is almost identical to the syntax for the .EQ directive. The only difference is that the .SE directive only allows you to use Global labels. This means that the label name should start with a letter from A to Z.
The expression may not contain forward referenced labels.
A variable label must be declared using the .SE directive. A label that is declared automatically or by the .EQ directive can not be changed to a variable anymore. Once the .SE directive declared a label as a variable label it is not possible to give it a new value with the .EQ directive anymore. New values can only be given using the .SE directive.
Variable labels may have different values in pass 1 and pass 2. They don't have to be in sync with each other.

After the definition of a variable label it is not possible to declare or use Local or Macro labels until the next declaration of a normal Global label. Subsequent changes to the value using the .SE directive are transparent to the use of Local and Macro labels.

The values of variable labels are not printed in the Symbol table because their value is not necessarily constant throughout the entire program.

See to it that a variable is declared during pass 1 of the assembly process. New labels can't be added to the Symbol table in pass 2 anymore.

A variable can not be used as a forward referenced value. This means that the current value is always used, not the value that the variable may have in the future.

Examples:

The 8048 processor does not allow lookup tables to cross a memory page boundary. This means that the most significant byte of the address must remain the same for the beginning of the table and the last byte in the table. Two Macros are working together to see if a table does not cross a page boundary.
The first Macro simply remembers the start memory page of the table. The second Macro's task is to see if that value hasn't changed.

OPEN      .MA
BEGIN     .SE   $/256              ; Remember the page
          .EM

CLOSE     .MA
          .XM   $/256=BEGIN        ; Quit macro if page is equal
          .DO   $*$1000000*?       ; Do only if LSB<>0 and pass 2
          .ER   *** Table page error
          .FI
          .EM

I agree that the second Macro calls for some extra explanation. The .XM directive will terminate the Macro's expansion immediately if the current memory page is equal to the value stored in the variable label BEGIN. If the pages are different we'll continue with the Macro.
The expression of the .DO directive is somewhat strange. But this is what it does. It multiplies the current location counter ($) by $1000000. This will result in a value that is 0 only if the least significant byte of the current location counter was 0. Remember that calculations in the SB-Assembler have an internal resolution of 32 bits and it won't warn you for overflows. This is a perfect example of a situation where we can take advantage of that. The overflowed value is simply ignored.
If this result is 0 the whole expression will be 0 as well (multiplying by 0 always results in 0). Thus the .DO expression is false and the next line is not assembled.
The purpose of the .DO directive here is to prevent an error message if the lowest byte of the location counter is 0 at the end of the table. In that case the last byte was stored on the last byte of the previous memory page, which still is OK even though the upper byte of the location counter differs.
The expression following the .DO directive also remains 0 if we're still at pass 1 of the assembly process. This allows us to see other, more severe errors before we have to change the table's start address.

Please note that these two Macros may be used as often as you like because the value of BEGIN may be changed over and over again. This would not have been possible using the .EQ directive.
Also note that Macro labels wouldn't have solved our problem either because they can't span across multiple Macros.

PS: This is only an example to demonstrate the use of variables. The problem presented here is so common for the 8048 that I have included 2 dedicated directives in 8048 family Cross-Overlays to replace these 2 Macros (.OT and .CT).

.SF    Symbol File

Syntax:

        .SF  filename[.ext]

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

Function:

The .SF directive allows you to create a Symbol file at the end of the assembly process.

Explanation:

The symbol file lists all Global constant labels followed by .EQ directives and their value. Such a Symbol file could be used to transfer all constants from one program into another program for linking purposes.
Please note that no Local labels or Macro labels are included in the Symbol file.

The Symbol table is opened by the .SF directive in pass 2 of the assembly process and will only be filled with the symbols at the end of pass 2. Therefore errors are only recognized in pass 2.

As usual drive letter and path are allowed together with the filename. The extension .ext is optional. The default extension is .SYM.
An already existing file with the name filename will be overwritten without prior notice.
The Symbol file may also be directed to a device instead of a file like PRN:, LPT1: or COM1:

The .SF directive may only be used once in a program.

.ST    STop

Syntax:

        .ST  [stopmessage]

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

Function:

The .ST directive is used to stop the assembly process temporarily. A message is displayed on the screen and the SB-Assembler waits until the operator presses almost any key.
This could be used for example to prompt the operator to insert another disk.

Explanation:

If no stopmessage is given the assembler will display the default stop message "Press almost any key to continue". Otherwise the text following the .ST directive will be displayed up to a maximum length of 79 characters. This limits the maximum length of the stop message to one line on the screen.

The stopmessage will be erased from the screen when the operator presses almost any key and then the assembly process will resume.
Except when the ESC key is pressed, in which case the assembly process is completely terminated. This is also true if the operator normally presses the ESC key during an assembly process.

Source lines that contain the .ST directive will never be listed in the list file and can not hold comments. All text following the .ST directive is considered to be the stopmessage.

Examples:

Prompt the operator for a new disk:

         .ST  Insert disk 2 and press any key

Warning! Don't use the drive that must hold different disks for writing target files, error files, or what ever other generated files to! This could even destroy the contents of the diskette written to.

.TA    Target Address

Syntax:

         .TA

Function:

This is an obsolete directive, originating from the Apple version of the SB-Assembler.

Explanation:

This directive was used on the Apple ][ version of the SB-Assembler to send generated code directly to memory, where it could be started directly. This is never possible on the PC however.

This directive will always report the "Not implemented in MS-DOS version error" message.

.TF    Target File

Syntax:

        .TF  [filename.ext[,format[,expression]]]

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

Function:

With the .TF directive you can open a target file in any of the available formats. This target file will be filled with the generated object code of your program.

Explanation:

The .TF directive, without parameters, will close an already open target file. Nothing will happen if no target file is open at that time.
If you want to include a comment behind an empty .TF directive a semicolon should precede this comment.

If a filename does follow the .TF directive an already open target file will also be closed. Then a new target file is created with the name filename. If that file already exists its length will be reduced to zero, effectively overwriting the file without prior notice!
As usual the filename may be preceded by a drive letter and legal MS-DOS path. The SB-Assembler will NOT provide a default extension with target files if you don't provide one. If you omit the extension .ext the created filename will not have an extension.

TIP: To avoid problems with other MS-DOS programs I advise you not to use the extensions .COM, .BAT, .EXE or .OBJ for your target files. The use of the extension .ASM for your target files will also cause confusion you clearly can do without. It could cause your source file to be overwritten accidentally.

Some target file formats won't allow you to create programs that are larger than 64 k bytes, provided that the maximum address used is not greater than $FFFF. So if you start your program at $F000 your program can't be any bigger than 4 k bytes!
There is no limit to the number of target files used during one assembly run. You can have as many target files filled with part of your program as you like. Only one of those target files will be open at any given time. Every time you open a new target file the previous one is closed.

Other target file formats allow you to create programs up to 4 G bytes, which will be sufficient for the next few years from now ;-)
The unformatted files BIN and HEX don't have an address field and can grow as large as your file system allows it.
Motorola has designed 3 different file formats, each with its own limit to file size. The address range for the S19 format is only 64 k bytes and so is the maximum file size. For format S28 the maximum address range is 16 M bytes (24 bits address). Finally the maximum file size for the S37 format is 4 G bytes (32 bits address).
The FPC file format is standard equipped with a 32 bit address range, so that file format is automatically capable of handling file sizes of 4 G bytes.
The Intel Hex file format originally has an address range of only 64 k bytes. When Intel noticed that this was not enough they invented some extensions to overcome this 64 k limit.
The first method of having larger file sizes was the use of segments, like in 80x86 processors. Every segment still can hold up to 64 k bytes. But at every 16 byte interval you can start a new segment of 64 k again. This could be quite useful for 80x86 processors, but is particularly difficult to handle for other processors because program counter and target address will be out of sync without obvious relation. The maximum target file size for segmented Intel Hex files is 1 M bytes.
The second solution they came up with at Intel is somewhat easier to comprehend. This solution uses linear segments. Again every segment is still 64 k bytes long. But at the end of this segment a new linear segment is started. Up to 64 k segments of 64 k bytes each can be used, which in fact is a 32 bit addressing range resulting in a maximum target file size of 4 G bytes.
The SB-Assembler can handle linear segmented Intel Hex files. Every time a segment boundary is crossed a new segment is started automatically.

Please note that all bytes generated by the program will be lost when no target file is open yet.

Warning: If the file filename already exists its contents will be erased and overwritten without prior notice.

It is also possible to send the target file to a device, instead of to a file. That way you can send your object code directly to a programmer or EPROM simulator. A device name should always end in a colon. All MS-DOS device names are allowed like PRN:, LPT1:, COM1:, NUL:. Avoid sending the object file to the screen (CON:) however, it will only cause a lot of gibberish to be displayed there.

The file format following the filename is optional. If it is not provided the default BIN format is used.

Please note: The .OR directive will close the unformatted file types BIN and plain HEX immediately because they don't support an address field. Please specify the start of the program before opening the target file if you intend to use one of these two file formats. If, for any reason, you do have to change the start address of the next code you can always use the .NO directive.
With all other file formats you may change the program address as often as you like.

These are the possible file format names:

AP1Apple 1 format
BINBinary format
E52Elektor EMON52 format (not a standard format!)
HEXHexadecimal format (every byte is translated to 2 hexadecimal digits coded in ASCII)
S19Motorola S19 format (64 kb range)
S28Motorola S28 format (16 Mb range)
S37Motorola S37 format (4 Gb range)
INTIntel Hex format (No opening segment if segment 0)
INSIntel Hex format (Always opening segment included)
SIGSignetics format
TEKTektronix format
FPCFour Packed Code format

What format you can use best depends on the capabilities of your EPROM programming device. I prefer the FPC format because it produces the most compact formatted target files. Unfortunately not many EPROM programmers support that code though.
The desired format is entered behind the filename, separated by a comma. Your choice is made by entering one of the 3 letter format names shown above.
The difference between the INT and INS formats applies only to the very first line sent to the target file. If the first address of your target file requires a segment of 0, the INT format will not include a segment definition line in your target file. This is useful for programs that don't grow larger than 64k, no segmentation is required there anyway. If you use the INS format the first line of the target file is always a segment address definition regardless of the segment value.

The format identifier may also be followed by an expression, separated by an other comma. This expression defines the maximum number of data bytes you want to have on each line in your target file. Only BIN files don't provide for this because they don't consist of lines.
Legal values for expression range from 8 to 32. Lower values will be increased to 8, higher values will be reduced to 32. If the optional expression is omitted the default line length will be 16 data bytes long.

The syntax of the .TF directive will only be checked during pass 2 of the assembling process. An existing file with the name filename will not be erased and overwritten before pass 2. So if any errors are encountered during pass 1 the old target file(s) will still exist unchanged.

All errors that occur in the parameter field of the .TF directive will result in a fatal error message to be reported. This will stop the assembly process immediately.

Examples:

         .TF   C:\OBJ\TARGET.BIN     Open BIN file (BIN is default)
         .TF   C:\OBJ\TARGET         Open BIN file (no extension)
         .TF   TARGET.BIN,BIN        Open BIN file
         .TF   TARGET.TXT,AP1,8      Open Apple 1 format
         .TF   TARGET.HEX,E52        Open EMON52 file
         .TF   TARGET.HEX,HEX        Open HEX file
         .TF   TARGET.INT,INT,32     Open INT file (32 bytes/line)
         .TF   TARGET.INT,INS        Open INS file
         .TF   TARGET.MOT,S19,8      Open S19 file (8 bytes/line)
         .TF   TARGET.MOT,S28        Open S28 file
         .TF   TARGET.MOT,S37        Open S37 file
         .TF   TARGET.SIG,SIG,0      Open SIG file (8 bytes/line)
         .TF   TARGET.TEK,TEK,100    Open TEK file (32 bytes/line)
         .TF   TARGET.FPC,FPC        Open FPC file
         .TF   TARGET.MOT,INT        Confusing, but legal
         .TF   TARGET.BIN,BIN,10     Legal, but length irrelevant
         .TF                         ; Close previous target file
         .TF   COM1:,INT,32          Send object to COM1:

Note on the Apple 1 format: Vince Briel started some sort of Apple 1 fever around the 30th anniversary of this legendarily computer. The original Apple 1 has only the cassette recorder as mass storage. However it is possible to expand the original Apple 1 with a serial interface and several replica versions are standard equipped with a similar serial interface.
All these serial interfaces have one thing in common: Everything received is literally "typed" to the Apple 1. This behaviour allows us to simply send a file to the Apple 1. And that is exactly what the Apple 1 format is meant for. Each line starts with an address, followed by a colon, which is then followed by the data bytes. Just like you would have done to manually type the code to the Apple 1.

.TI    TItle

Syntax:

        TI  [S],[expression[,title]]

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

Function:

The .TI directive is used to set the page length and title for each page in the list file.

Explanation:

If only the .TI directive is given on a source line, or when the text following the .TI directive is more than 9 spaces away from it, all default parameters are set. This means that the Single Sheet mode is switched off, the page length is set to infinite and the title is erased. The infinite page length implies that no form feeds are inserted after a certain number of lines.
Please note that these are the default settings for list files. So these settings also apply if no .TI directive is present in your source file.

The Single Sheet mode is selected if the first character of the operand field is a single S, or an S followed by a comma. This means that the SB-Assembler will wait for the operator to insert a new page in the printer when the previous page is full. The user is prompted to press almost any key when the new page is loaded in the printer with the message: "Insert new sheet and press any key".
The SB-Assembler will not ask you to insert the first sheet of paper though. So the operator should provide the first sheet before starting the SB-Assembler.
Please note that this function was included when ink jet and laser printers were not as common as they are today. The Single Sheet mode is a bit outdated nowadays.

The expression defines the number of lines that are to be printed on a page in the list file. The minimum number of lines is 8, the maximum number is 254. All other values result in a "range error" to be reported.
A form feed is generated every time the number of lines reaches the pre-set value, starting a new page. The title and a page number is printed above each new page.

The title can be any piece of text, up to 127 characters in length. The title is treated as literal text, where case and spaces are not changed. The title is always printed above each new page in the list file. It does not matter if that page is started automatically or was forced by the .PG directive.
The .TI directive will force a new page to be started with the new title printed above it.

The title may be changed as often as you want during the assembly. Every time you change the title, using the .TI directive, a new page is started with the new title above it.

The .TI directive is never listed in a listing file itself. Therefore it does not accept comments. Everything following the title will be treated as part of the title itself.

The .TI directive is only parsed during pass 2 of the assembly process. Errors will not be discovered during pass 1.

Examples:

; Set the list page length to 55 lines, without a title
         .TI  55

; Set the page length to 55 lines, with title
         .TI  55,This is the title

; Set the page length to 40 lines, with title and
; Single Sheet mode
         .TI  S,40,New title

; Switch off auto page mode and titles.
         .TI
.TW    Target Write

Syntax:

         TW  string¦#expression[,string¦#expression[,...]]

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

Function:

This directive allows you to write strings directly to the target file.

Explanation:

This command will flush the current target file's line buffer and then it writes a string directly to the file. The string can be anything, but usually holds some remarks or programming device commands.

I can think of two main reasons why you would want to write to the target file directly.
The first reason is to enter some comments in the target file. Be careful though, not all programming devices allow you to enter comments in the target file. Comment lines usually begin with a single quote or an exclamation point.
The second reason is to embed programming device commands directly in the target file. This way the target file can be sent directly to the programming device during assembly. Remember though to remove the commands from the target file if you intend to share it with others who don't have such sophisticated programming devices.

The syntax of the .TW directive is somewhat comparable with that of the .AS directive, with the only exception that it is not possible to create strings with a negative ASCII polarity. You may use either a delimited string, or a separate byte per parameter. Multiple parameters must be separated by commas.
You may even use characters from the extended IBM character set if you like.

Please note that strings are not terminated with a CR or LF automatically! If you do want to end the string with a CR/LF pair you will have to enter them as normal byte parameters.

This directive should be used with some care because you can make the target file useless if you write something to it that your programming device doesn't understand. Also be very careful not to write directly to a binary formatted file because they rarely allow comments or other commands.

Strings may not be empty and must be terminated by the same delimiter that was used to start the string, otherwise an error will reported.
Bytes must evaluate to a value of 0 to 255, otherwise you'll get a "Range error".

The .TW directive is only parsed during pass 2 of the assembly process. Errors will not be discovered during pass 1.

Please note that it is not possible to put comments or commands at the absolute end of the target file, unless the target file is a binary or HEX unformatted file. The reason for this is very simple. The "end of file" line is only written just before the target file is closed. Therefore the "end of file" line is always the last line to be written to the target file, simply because the file is closed immediately afterwards. And you can't write to an already closed file anymore.
This may cause some problems if your programming device requires some instructions to be given at the very end. Usually these problems occur only when the target file is sent directly to the COM port. In that case we can simply overcome the problem by reopening an new target file to the COM port, this time as binary format.

Examples:

         .TF   TWTEST.HEX,INT
         .AS   /Test/
         .TW   /'Remark line/,#$0D,#$0A
         .AS   /Test/

The program above generates the target file below:

:04000000546573745C
'Remark Line
:040004005465737458
:00000001FF

Omitting the #$0D,#$0A part of the .TW directive in the example above would result in the probably useless file below:

:04000000546573745C
'Remark Line:040004005465737458
:00000001FF

Please note that the program below will generate a remark line just before the "end of file" record in the target file. The "end of file" line is always the last line of the target file!

         .TF   TWTEST.HEX,INT
         .AS   /Test/
         .AS   /Test/
         .TW   /'Remark line/,#$0D,#$0A
:04000000546573745C
:040004005465737458
'Remark Line
:00000001FF
.XM    eXit Macro

Syntax:

        .XM  [expression]

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

Function:

The .XM directive prematurely exits an expanding Macro. This premature exit can be caused conditionally or unconditionally.

Explanation:

If the optional expression is omitted the .XM directive will prematurely exit the expanding Macro. If the expression is given the expanding Macro will be terminated when the expression evaluates to be true, i.e. unequal to 0.

The expression may not contain any forward referenced labels. The expression must follow the .XM directive within 9 spaces, otherwise it is treated as comment.

The unconditional exit is normally only used in co-operation with conditional assembly directives .DO, .EL and .FI. Without any of these conditional directives the use of an unconditional .XM does not make much sense.
This presents us with a little problem. If the condition is started inside the Macro then the .XM directive will immediately terminate the Macro. Therefore the .FI directive that is also part of the Macro will never be executed. This results in a corrupted conditional stack that holds all pending true and false conditions. That is why the .XM directive will pop one condition from the condition stack, like the .FI directive would have done.
Please note that the .FI directive itself is still required to terminate the conditional part of the code in case the condition was not true! The .FI directive normally must follow the unconditional .XM directive in your source file. Any instructions between those two directives would never be interpreted anyway.

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

Examples:

The following example shows us a Macro that can push up to 3 registers on the processors stack. You can expand the Macro to handle even more than 3 registers yourself.

1   PUSH      .MA    reg1,reg2,reg3
2             PUSH   ]1        ; Push register 1 on the stack
3             .XM    ]#=1      ; Done if only 1 parameter
4             PUSH   ]2        ; Push register 2 on the stack
5             .XM    ]#=2      ; Done if only 2 parameters
6             PUSH   ]3        ; Push register 3 on the stack
7             .EM
8
9   TEST      >PUSH ACC,PCL,PCH
M1            PUSH  ACC
M2            .XM   3=1
M3            PUSH  PCL
M4            .XM   3=2
M5            PUSH  PCH
10
11            >PUSH ACC
M1            PUSH  ACC
M2            .XM   1=1
12
13            >PUSH B,ACC
M1            PUSH  B
M2            .XM   2=1
M3            PUSH  ACC
M4            .XM   2=2
14            NOP           Rest of the program
 

© 2002, San Bergmans, Oisterwijk, The Netherlands
http://www.sbprojects.com