Search   
Home  Print View  

 

Programmer's Manual

Branch Content

Directives

By directive we understand those commands placed in assembly code that are targeted to the Assembler, as opposite to instructions which are targeted to the computer running the resulting binary code.

Directives start with the sharp character (#) followed by the directive's name, then the argument. These three parts are separated from each other by the mean of spaces or tabs.

The following directives are currently available.

Include

Syntax:

#include FILE_NAME

This directive causes the given file (FILE_NAME) to be opened and processed immediately as if it were part of the current file. This action is recursive so further #include directives found in included file will be processed in the encountered order.

The #include's argument (FILE_NAME) is the name of a source file expected to be in the "include directory"; the later was passed explicitly in the command line (second argument) when the assembler was launched, or was automatically extracted otherwise from the source-file path (first argument) at that time.

You can also specify a full path in the #include directive. That may be the case of being using reusable code from files placed in separate directories for better organization. The assembler will realize whether the #include argument is a filename or a full path and it will act accordingly. Either case, if the file does not exist, an error will be reported.

A given file can be #included more than once. This might be used to compensate for the lack of Macros, as in the following example:

      ; Using reusable code for sorting a list in memory.
      ; The included code accepts arguments in registers d, c.      

      mvi d, BUFF        ; List in memory to be sort out
      ld  c, BUFF_SIZE   ; Certain var in memory holding the buffer's size

      ; The included code does the job...
      #include /home/armando/src/lib/quick_sort.asm
      

Org

Syntax:

#org ADDRESS

Sets the origin address, effective since the first instruction following the directive's line. ADDRESS can be either a symbol or a numerical expression.

The following statements are valid:

START  equ 0x400
#org   START
#org   0x400

The following will result in error: "Illegal use of string":

#org  $START

Data

Syntax:

#data EXPRESSION

This directive is useful for filling areas of memory with fixed data such as lookup tables and string messages, as illustrated below.

#define   MSG_TABLE = 0x800

#org MSG_TABLE
#data     $File not found
#data     $Stack overflow

Starting at address 0x800 will be the (null-terminated) string "File not found" followed by the string "Stack overflow" (30 words total).

Define

Syntax:

#define SYMBOL = VALUE

This directive defines a symbol by indicating the expression (VALUE) it represents. The same can also be done with the equ construct for numeric expressions as illustrated in previous examples.

Actually, support for equ was introduced in H1ASM for compatibility with such "traditional" construct. However, the #define directive is conceptually more robust and more powerful in practice since it allows for symbolic strings too.

The previous example could also be written this way:

#define   MSG_TABLE         = 0x800
#define   ERR_MSG_F_NOFOUND = $File not found
#define   ERR_MSG_S_OV      = $Stack overflow

:MSG_TABLE

#data     ERR_MSG_F_NOFOUND
#data     ERR_MSG_S_OV

Set

Syntax:

#set VAR = VALUE

The set directive is used to assign a value to a variable. If the variable didn't exist, it is created at that time. VALUE can be either a symbol, an expression, another variable or even the same variable (which doesn't sound too much useful but it is legal anyways).

Once a variable is created, it can be used in instructions in place of the operand, as illustrated in the following example.

#define    BUFF_TAPE_1    = 0x4000
#define    BUFF_TAPE_2    = 0x4100

; Call subroutine passing argument in variable:
#set  @_buff = BUFF_TAPE_1
call READ_TAPE

; Call subroutine again passing a different argument in the same variable:
#set  @_buf  = BUFF_TAPE_2
call READ_TAPE


;
; -- SUBROUTINE --
;
:READ_TAPE
      ; Variable used as operand:
      ld   e, @_buff

Symbols and variables can not share names; failure to observe this will result in errors reported by the assembler. To overcome this limitation, naming conventions must be employed. We suggest to write symbols with uppercases and variables, written with lowercases, to start with the '@' character as illustrated in the previous example.

The need for variables comes from the lack of macros in H1ASM. In fact, you can "encapsulate" reusable generic code into separate source files, then #include it in your "client code" passing arguments through variables. Here is an example:

#set  @_quick_sort_buff       = BUFF_ADDR
#set  @_quick_sort_buff_size  = BUFF_SIZE_VAR

; The included code does the job. It uses the above variables:
#include /home/armando/src/h1_lib/quick_sort.asm

Format

Syntax:

#format FORMAT

Specifies the output format as explained in section Assembler Output.

Homebuilt CPUs WebRing

JavaScript by Qirien Dhaela

Join the ring?

David Brooks, the designer of the Simplex-III homebrew computer, has founded the Homebuilt CPUs Web Ring. To join, drop David a line, mentioning your page's URL. He will then add it to the list.
You will need to copy this code fragment into your page.

Project start date: May 13 of 2009