home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-22 | 163.6 KB | 2,894 lines |
- PCMAC USERS GUIDE
- PCMAC Universal Macro Assembler for
- the IBM PC XT\AT\PS2 and Compatible Computers
-
- What Is PCMAC ?
- ---------------
- PCMAC is a two pass, symbolic cross assembler for the IBM
- PC\XT\AT\PS2 computers. This assembler is a special one, because
- it is not dedicated to any processor. The user of PCMAC can decide
- what kind of assembly language to use, and what kind of code he
- wants to be generated. Therefore a very special macro language is
- supported in PCMAC that is powerful enough to define any assembly
- language like Z80 or MC68000. The assembler supports many
- possibilities to maintain big assembly programs. Some of the
- features:
- - special string and character expressions
- - full C language like expressions
- - powerful primitive commands to build up higher level
- assembly instruction
- - directive and command line option driven listing
- - symbol table listing
- - fully compiled binary or linkable object code output chosen
- by the user
- On the distribution disk you have the PCMAC assembler, a linker
- that links the object file output of the assembler, and some other
- files.
- Why You Need It
- ---------------
- You need PCMAC if you intend to develop assembly programs on
- your PC for some rarely used processor for which there is no
- assembler.
- Mr. Developer bought a seven-a-half-bit processor called
- BRXX7.5 none heard of it before. He had documentation for it, and
- he decided to use it in a control circuit. He built a control
- system driven by the BRXX7.5 and he tried to develop a program for
- it. At first he thought to develop the program in a high level
- language but there was no compiler targeting the BRXX7.5. Then he
- tried to develop the program in assembly language, but even before
- the first pass of the compilation an error message appeared:
- No assembler present for your processor.
- Mr. Developer decided to have an assembler written. He asked Mr.
- Lazy, a programmer, to write an assembler for him. Mr. Lazy
- accepted the job, and said to have done the assembler in six month
- for 2000 bucks. Of course the assembler won't be very easy to use,
- and may generate false code in the first versions, but any times
- such a problem arises Mr. Developer can phone him, and he will fix
- the bug in two weeks.
- Well, this is not the story that makes Mr. Developer happy.
- Then he decided to buy the new PCMAC assembler. He did it, read
- the users guide through and defined his special assembly language
- in two days. He made some mistakes in his first version, but PCMAC
- once warned him, when it could, and in another time he found the
- bug himself looking at the highly readable listing of his program.
- He could find the bug in the macro definition in two minutes and
- also could correct it immediately.
- Mr. Developer had an assembler that compiled his special
- assembly language. But many times he wrote the instruction EX
- DE,HL that changed two registers into the form EX HL,DE. The
- assembler pointed out that it could not compile the instruction
- many times
- . Then Mr. Developer included this instruction, as a
- new form of the other one, and PCMAC, since that time, could
- compile the programs. If he had an ordinary assembler he couldn't
- do that.
- Finally Mr. Developer finished up his work soon and his boss
- was very great to give him a salary raise.
- This is the story of Mr. Developper and it can be the story of
- you.
- How to Use?
- -----------
- It is very easy to use. You have to prepare a text containing
- your assembly program. There are many good editors for the PCs.
- You can use any of them. Suppose you prepared an assembly program
- and the program is now in the file MYFIRST.ASM. Now type at the
- DOS prompt:
- PCMAC MYFIRST.ASM
- The word PCMAC on the start of the line is the name of the
- assembler and typing it invokes DOS to start PCMAC. The rest of
- the line is the name of the program that you want PCMAC to
- compile. PCMAC having been loaded reads the name of the assembly
- program and tries to compile it. It writes some text to the screen
- that says that there were errors in your assembly file and does
- not generate output. After correcting the bugs in your assembly
- program you should type the same line again for the DOS promt, and
- happily read that there was no error in your assembly file, and
- the compilation was successful. Now list the directory, where you
- work, with the DOS command 'dir', and see that there is a file
- named: MYFIRST.TSK. This file contains the compiled code of your
- program. Try to load into your target machine and start. Well this
- is the point where we can not give you any advice how to do
- because it can vary from user to user. External machines are often
- connected to the RS232C channel, and you can use a program was
- written in 80X86 assembly, in C, in PASCAL or in any language that
- loads the code into the external machine.
- The Assembly Language
- ---------------------
- It is difficult to speak about the assembly language of PCMAC
- because every user defines his own assembly. However there are
- some main rules that stand for every user defined assembly syntax.
- An assembly program consists of lines, and every line contains
- at most one instruction. The instructions are terminated by the
- new line character at the end of the line or by a semicolon ; that
- can be followed by comment. Every line contains two parts. The
- first part is the label and the second is the instruction. The
- labels start in the first column of the line and are terminated by
- a space or tabulator. The instructions start at any position, but
- a space or tabulator character has to precede them. Many case it
- is neccesary to start a label not in the first column. It can be
- for the sake of the readability. In such case the label has to be
- terminated by a colon. Any part of a line can be missing. A line
- can contain only instruction without label, only a label or only
- comment or even no comment. So a line can even be empty. Some
- examples:
- 1.)
- LABEL_IN_THE_FIRST_COLUMN LD A,B ;COMMENT
- The label LABEL_IN_THE_FIRST_COLUMN is a long label that starts
- in the first column and separated from the instruction by a
- space. It could be separated by many spaces. Many spaces in this
- case work like one. The command is LD A,B and terminated by the
- semicolon ;. The rest of the line is comment. Another example:
- 2.)
- LABEL_NOT_IN_THE_FIRST_COLUMN :
- This line contains only a label that has to be terminated by a
- colon, even if there is no instruction following. A label has to
- start with a letter or with the underscore character and can
- contain letters, numbers and the underscore character. A label can
- be as long as you want but should not exceed the maximal length of
- a line that is 500 character. This is an exceptable limit. It is
- regarded to use long labels that tell you the meaning. The
- assembly format of PCMAC always pays attention to the possibility
- of readable programming.
- 3.)
- Well, this example is difficult to typeset. The line above wants
- to present an empty line.
- 4.)
- ;This text is comment
- This line contains only a comment.
- 5.)
- LABEL LD a,B ;Comment
- This is a line that contains a label starting in the first
- column, instruction separated by a space and comment.
- A line can contain a directive. Directives start in the first
- column with a sharp # character. This looks like in C language,
- but PCMAC has much more directives than C language. As a matter of
- fact PCMAC currently has 28 kinds of directives. You can read
- about directives in details in a separate chapter. Example:
- #dw hl
- This line is a directive that tells PCMAC to generate words on
- order: higher byte, lower byte. Some line looks:
- #dw lh ; Usual convention
- that changes the order to the usual and the line contains comment.
- How PCMAC Generates the Code
- ----------------------------
- The main reason to use PCMAC to generate binary file
- from a text file. The text file can be read easy by human, while
- the binary file can be read by some program or machine. From the
- point of view of code generation the assembly lines can be
- grouped into two groups. Instructions of the first group generate
- code, while the instructions of the second group do not.
- PCMAC reads the lines twice. One going through the lines
- is usually called PASS. This is why PCMAC is called a two pass
- assembler. In the first pass PCMAC decides how big memory is
- needed for the code, and the second pass generates the code. After
- the first pass PCMAC reserves place to store the code. When a line
- containing instruction that generates code encounters in the
- second pass PCMAC stores the code in the reserved area at a place
- that is shown by the variable $. This variable is a predefined
- variable of PCMAC that you even can reference in your assembly.
- This variable in other assemblers is usually called Location
- Counter. PCMAC increments this variable after generating a byte.
- If you set this variable to a certain value than the next byte
- would be generated to the location that is pointed by the value.
- If you set this variable to point a location where PCMAC already
- had generated a byte then PCMAC will overwrite the old value with
- the next byte. Some assemblers do not allow to generate bytes with
- descending addresses. However in some cases it is neccessary to do
- so.
- Primitives
- ----------
- Primitives are instructions that are known by the PCMAC
- assembler itself. They are primitive, but they has to be used to
- build up macros, assembly language. These primitives are the same
- as they are in any other assembly language. These primitives are:
- DB,DW,DD,DRB,DRW,DRD,VAR,EQU,EXTERN,EXTRN,PUBLIC
- The first six directives generate code the others do not. The
- instructions in details:
- DB Abbreviation of Define Byte. The syntax of this
- instruction is:
- DB expression1,expression2,...,expressionN
- or
- DB string
- The instruction generates so many bytes as many
- expressions there are after the keyword DB. PCMAC
- first evaluates the expressions and generates
- successive bytes to hold the values. If a value
- does not fit into the interval [-128,255] then
- PCMAC generates an error message. This interval
- allows you to treat a byte as signed value. In
- that case the assembler generates a byte that
- contains the value in two's complement code. In
- other words: if the value is less than zero then
- the assembler adds 256 to it before generation.
- This instruction can also be used to declare
- strings. From the point of view of the code
- generation a string is nothing else then a byte
- vector. Every character of a string is a byte,
- and these bytes are generated succesively when
- using a string instead of an expression. The
- syntax of strings is detailed in a later chapter.
- DW Abbreviation of Define Word. The syntax of this
- instruction is:
- DW expression1,expression2,...,expressionN
- The instruction generates two bytes for every
- expression. The expressions are treated as words
- ie: two byte values. If a value does not fit into
- the interval [-32768,65535] PCMAC generates an
- error message. This interval allows you to treat
- a word as signed value. In that case the
- assembler generates a word that contains the
- value in two's complement code. In other words:
- if the value is less than zero then the assembler
- adds 65536 to it before generation. The order of
- the bytes in a word is: lower byte, higher byte
- by default. This ordering can be redefined by the
- #DW directive. String can not take place between
- the expressions.
- DD Abbreviation of Define Doubleword. The syntax of
- this instruction is:
- DD expression1,expression2,...,expressionN
- The instruction generates four bytes for every
- expression. There is no limit for the value of an
- expression, because PCMAC uses 32 bit arithmetic
- and it makes impossible to be out of the interval
- of doubleword. The generation takes place in two
- steps. PCMAC splits up the doubleword into two
- words and generates words. The order of the word
- generation is: lower word, higher word by
- default. This ordering can be redefined by the
- #DD directive. The order of the bytes between the
- words is the same as if the words were generated
- by DW primitives. They go through the same
- ordering procedure. In other words PCMAC
- generates two DW instructions for a DD. Strings
- can not take place among the expressions.
- DRB Abbreviation of Define Relative Byte. The syntax
- of the instruction is:
- DRB expression1,expression2,...,expressionN
- The expressions are treated as 32 bit values, and
- the generated value is the value of the
- expression minus the value of the variable $ plus
- one. At first glance this procedure seems
- sophisticated and useless. The power of this
- primitive is that many instructions of
- microprocessors refer to relative addresses and
- this is the way those addresses are treated when
- byte offset is given. The generated bytes added
- to the address of the next byte will give the
- target address. PCMAC will generate a warning
- message if some of the expressions is not
- relocatable. PCMAC will generate error message if
- the modified value is not in the range
- [-128,127]. A string can not take place among the
- expressions.
- DRW Abbreviation of Define Relative Word. The syntax
- of the instruction is:
- DRW expression1,expression2,...,expressionN
- The expressions are treated as 32 bit values, and
- are modified the same way as in the instruction
- DRB. A main difference is that the modificating
- value is the value of the variable $ plus two
- because this instruction generates two bytes.
- This primitive is useful when relative addressing
- takes place with word offset. PCMAC generates
- warning message if an expression is not
- relocatable and will generate error message if
- the modified value is not between the interval
- [-32768,32767]. A string can not take place among
- the expressions.
- DRD Abbreviation of Define Relative Doubleword. The
- syntax of the instruction is:
- DRD expression1,expression2,...,expressionN
- The expression are treated as 32 bit values and
- are modified the same way as in the instructions
- DRW or DRB. A main difference is that the
- modificating value is the value of the variable $
- plus 4 because this instruction generates four
- bytes. PCMAC generates warning message if any of
- the expressions is not relocatable.
- EXAMPLES:
- Let us look at the next program!
- ;Program to demonstrate the primitives DB,DW,DD,DRB,DRW and DRD
- ;Set the variable $ to zero
- ;This instruction is useless because this is the default.
- $ := 0
- ; Generate byte 11h
- DB 11h
- ; The next instruction generates byte 0FEh because
- ; now $=1, $+1=2 and 0-2=-2 equals to 0FEh in two's complement.
- ; NOTE: This instruction makes PCMAC to give a
- ; warning message because the expression 0 is not
- ; relocatable.
- DRB 0
- ; The following instruction generates two bytes.
- ; The generated bytes are 0FFh and 00h
- LABEL1
- DRB LABEL1,LABEL2
- LABEL2
- DW 1234h ; The generated bytes are 34h and 12h respectively.
- DD 12345678h ; The generated bytes are
- ; 78h, 56h, 34h, 12h respectively
- DRW LABEL3 ; The generated bytes are zeroes
- LABEL3 DRD LABEL3 ; The generated bytes accord to the value -4
- ; -4=0FFFFFFFCh in two's complement,
- ; so the generated bytes are 0FCh,0FFh,0FFh
- ; and 0FFh
- ;End of EXAMPLE PROGRAM
- VAR This instruction declares variables.
- The syntax of the instruction is:
- VAR identifier1,identifier2,...,identifierN
- The identifiers are treated as variables
- following the instruction. If an identifier appears on the left
- hand side of an assignment that was not declared with a VAR
- instruction then PCMAC generates a warning message. The initial
- value of a variable is definitily zero.
- EQU This is a special instruction that assigns a
- value to a label. The syntax of the instruction
- is:
- label EQU expression
- label : EQU expression
- The label has to appear on the place of labels in
- the line as it was mentioned earlier. The value
- is assigned to the label. This is the only
- exception when a value that is not the value of
- the variable $ is assigned to a label. In any
- other case if a label stands on the left hand
- side of a line the value that is assigned to it
- is the value of the variable $ when PCMAC starts
- to read the line.
- EXTERN
- EXTRN These instructions are the same, so we refer to
- it as one instruction. This instruction only has
- two different forms because it is often mistyped
- by assembly programmers. The syntax of the
- instruction is:
- EXTERN label1,label2,...,labelN
- This instruction declares the labels to be
- external. It means that there is no value
- assigned to the label in the assembly program and
- this is because it is defined in an other part
- that is compiled separately. Such a label must
- not appear in an expression. The only exception
- is when the label itself forms an expression. For
- example we can write:
- DW external_label
- where external_label is an external label. The
- instruction can only be used when PCMAC was
- invoked with the -o option. This option forces
- PCMAC to generate object file instead of
- executable task file. The references can not be
- resolved by PCMAC. The assembler only generates a
- note for the linker about the unsolved reference.
- When the linker reads the note solves the
- reference. If nor the option -o neither the
- option -t is present then PCMAC generates an
- error message when an EXTERN or EXTRN instruction
- appears.
- PUBLIC This instruction declares a label to be public.
- This instruction can only be used if PCMAC was
- invoked with the option -o. This instruction
- means that PCMAC makes a note about the label in
- the object file, and the linker can solve the
- references to this label that are present in
- other modules. The instructions EXTERN and PUBLIC
- are as husband and wife. If nor the -o neither
- the option -t is present when invoking PCMAC then
- PCMAC generates a warning message if the
- instruction appears.
- EXAMPLE:
- Here we present two simple programs. Assume that the programs are
- stored in the files TTHL.ASM and HL2.ASM. The first one
- (TTHL.ASM):
- ;A program that multiplies HL by two
- TWO_TIMES_HL
- ADD HL,HL
- RET
- PUBLIC TWO_TIMES_HL
- The other program (HL2.ASM):
- ;Program that calls TWO_TIMES_HL
- EXTERN TWO_TIMES_HL
- CALL TWO_TIMES_HL
- The user can compile these programs with the DOS commands:
- PCMAC -o TTHL.ASM
- PCMAN -o HL2.ASM
- LINK TTHL.O HL2.ASM
- The first two commands compile the assembly files and generate
- object files. The last command links the files together.
- Directives
- ----------
- The current version of PCMAC knows 28 directives of 8 group.
- A directive always appears on the start of a line preceded by a
- sharp character #. The directives:
- 1. include, macros, lib
- 2. fatal, error, warning, message, pause, list, ilist
- 3. if, endif, else, elsif, ifdef, ifndef
- 4. octal, decimal, char
- 5. dw, dd
- 6. macarg, macnum
- 7. stack, pop, push, clostack
- 8. while, wend, repeat, until
- Collecting the directives into groups accords to their effects.
- Here we present all the directives with some text that can work as
- short reminder.
- 1. Including directives.
- include includes assembly file,
- macros includes assembly file while the first pass
- lib includes compiled macro library
- 2. Listing directives.
- fatal generates an error message and stops PCMAC
- error generates an error message
- warning generates a warning message
- message generates a message
- pause supresses compilation until ENTER is pressed.
- list switches the listing on and off
- ilist switches the listing of include files on and off
- 3. Conditional directives.
- ifdef
- ifndef
- if switches the compilation on or off.
- endif closes a block that was opened with some if...
- else
- elsif switches the compilation on or off.
- 4. String option setting directives.
- octal changes string radix octal.
- decimal changes string radix decimal.
- char redefines character code.
- 5. Code ordering directives.
- dw sets ordering of bytes in a word.
- dd sets ordering of words in a doubleword.
- 6. Macro option setting directives.
- macarg redefines the macro argumentum character.
- macnum redefines the macro number character.
- 7. Compilation stack handling directives.
- stack opens a stack.
- pop pops a value from the top of the stack.
- push pushes a value onto the stack.
- clostack closes a stack.
- 8. Loop directives.
- !!!!! These directives can ONLY be used inside of a macro. !!!
- while start a while loop
- wend end a while loop
- repeat start a repeat loop
- until end a repeat loop
- The rest of this chapter tells you the effect and usage of all
- directives. However there are some definition that you can not
- understand until you are not familiar with string and macros. We
- recommand you to skip the definition of group 4 if you are not
- familiar with strings and groups 6 and 8 if you are not familiar
- with macros. Having learnt what PCMAC call string and macro you
- can return to this chapter.
- Group No 1.
- #include "file name" or #include <file name>
- This directive makes PCMAC to suppress reading the actual
- file and open the file that is named following the directive. This
- directive has the same effect as if the file was copied into the
- place of the directive into the current file. The directive has
- two forms. In the first case the name of the file is enclosed
- between "s. In the second case between < and >. If the file name
- is enclosed between "s then PCMAC searches the file in the current
- DOS directory if not path presents in the file name. If the file
- name enclosed between < and > then PCMAC searches the file in the
- directory that is pointed by the environment variable INCLUDE. A
- file that is included from an other one can also include. Include
- directives can be nested into 5 level deep.
- EXAMPLE:
- Assume that we have set the environment variable with the DOS
- command:
- SET INCLUDE=C:\PCMAC\INCLUDE
- or
- SET INCLUDE=C:\PCMAC\INCLUDE\
- There is no difference between the two settings from the point of
- view of PCMAC. Assume that the current directory is
- C:\PCMAC\SOURCE. The directive:
- #include "DECL.ASM"
- will include the file C:\PCMAC\SOURCE\DECL.ASM. The directive
- #include <DECL.ASM>
- will include the file C:\PCMAC\INCLUDE\DECL.ASM. The directive
- #include <SYS\MACROS.ASM>
- will include the file C:\PCMAC\INCLUDE\SYS\MACROS.ASM. The
- directive
- #include <C:\ROOT.ASM>
- forces PCMAC to try to open and read a file named
- C:\PCMAC\INCLUDE\C:\ROOT.ASM. It is an invalid file name so PCMAC
- will fail trying to read, and generates an error message. If we
- use the directive
- #include "C:\ROOT.ASM"
- PCMAC will include the file "ROOT.ASM" from the root directory of
- the drive C.
- macros "file name" or macros <file name>
- This directive has almost the same effect as an #include.
- The difference is that this directive is neglected in the second
- pass. This is useful to collect the macro definitions, the EQU
- primitives into a file and to include it with the directive
- macros. These lines are skipped while the second pass. The
- directive is called macros, because usually macros are collected
- in a file that is included only in the first pass. The meaning of
- the delimiters of the file name is the same as in case of the
- #include directive. One can say that
- #macros "file"
- can be used instead of the three lines:
- #if PASS = 1
- #include "file"
- #endif
- A file that was included with the directive macros can contain a
- macros directive or even #include directive. Obviously the file
- that is included into a file that is included with a macros
- directive will only be included only in the first pass. The
- nesting of their directive can be 5 level deep together with the
- opened files of the directive include.
- #lib "file name" or #lib <file name>
- This directive forces PCMAC to open and read a file that
- was generated by PCMAC and containing only compressed macro
- definitions. If a file contains only macro definitions, and no
- line generating code, then this program can be compiled with the
- -K option. If PCMAC was invoked with the -K option it only goes
- through one pass, and finishing the pass creates a file that
- contains the macros that were defined. If we have a file
- MACROS.ASM containing only macros and we compile it with the
- command line:
- PCMAC MACROS.ASM MACROS.LIB -K
- then including the result file MACROS.LIB with the directive lib
- has the same effect as including the original file MACROS.ASM with
- the directive macros or include. The difference is that including
- a compressed lib file is much faster because PCMAC checked the
- syntax in an earlier compilation. The delimiters have the same
- meaning as in the case of macros or include.
- Group No 2.
- #fatal string
- #error string
- #warning string
- #message string
- These directives generate message that appears on screen
- and in the listing file if it exists. These directives are useful,
- when creating macros. An example can be seen in the Z80 macro
- definition file:
- macro("LD\ *,*",_SS,_SS)
- #if #0 == 6 && #1 == 6
- #error "LD (HL),(HL) is invalid."
- #else
- DB 40h+(#0<<3)+#1
- #endif
- endm
- This macro defines the instructions that load 8bit from a register
- to a register, or from the memory location addressed by HL to a
- register or backward. However to load from the memory location
- pointed by HL to the same memory location is invalid. If a code
- encounters that would accord to the assembly instruction LD
- (HL),(HL) then the processor Z80 gets into a halt state. There is
- a separated instruction for this purpose, HALT. In other words, if
- the programmer writes the line:
- LD (HL),(HL)
- then he probably wants something else than HALT. This macro does
- not compile this line, but generates an error message instead. The
- message appears on the same place where the errors generated by
- PCMAC appear, and PCMAC treats the message as an error message
- generated by itself. Continues the compilation to discover other
- mistakes, but having finished the two passes does not generate
- object nor task file.
- One could define the macro in the following way:
- macro("LD\ *,*",_SS,_SS)
- #if #0 == 6 && #1 == 6
- #fatal "LD (HL),(HL) is invalid."
- #endif
- DB 40h+(#0<<3)+#1
- endm
- In this case the compilation halts having put out the message.
- This is a very strong wake up for the programmer, and the fatal
- directive is regarded to be in use when a really serious error
- appeared. PCMAC generates fatal errors e.g. when it can not open a
- file.
- One could define the macro in the following way as well:
- macro("LD\ *,*",_SS,_SS)
- #if #0 == 6 && #1 == 6
- #warning "LD (HL),(HL) is invalid."
- #endif
- DB 40h+(#0<<3)+#1
- endm
- If a line LD (HL),(HL) encounters and this macro definition is
- valid, then the message appears as warning and PCMAC treats as a
- warning. The compilation goes on, and having finished the two
- passes PCMAC writes out the object or task file.
- The last of this three directives is message. This
- directive generates a message appearing on the screen, and in the
- list file, but this event is treated neither an error nor a
- warning. This is only a message. PCMAC puts it out and forgets all
- about it. You can use it if you run PCMAC on a two-disk-drive
- machine and you compile very large files. In this case you can
- create a main file that contains only directives on one floppy
- disk, and the other files on other floppy disks. You start to
- compile the main file (eg. MAIN.ASM ) on drive A, and include the
- files containing the program fragments on drive B. The program
- MAIN.ASM can look like this:
- ;MAIN.ASM includer of a very large program
- #message "Put the disk containing SUB1.ASM into the drive B:"
- #message "and press RETURN!"
- #pause
- #include "B:SUB1.ASM"
- #message "Put the disk containing SUB2.ASM into the drive B:"
- #message "and press RETURN!"
- #pause
- #include "B:SUB2.ASM"
- #message "Put the disk containing SUB3.ASM into the drive B:"
- #message "and press RETURN!"
- #pause
- #include "B:SUB3.ASM"
- ;End of file MAIN.ASM
- You should not forget to use the pause directive before the first
- #include, because finishing the first pass the disk that contains
- SUB3.ASM but not SUB1.ASM is in the drive B.
- #pause
- This directive makes PCMAC to stop until one presses the
- key ENTER. The usage of this directive was described for the
- directives just above.
- #list expression
- #ilist expression
- These directives switches the listing of the compilation.
- They have only effect if the command line option -l was given on
- invocation of PCMAC. If the expression is true (not zero) then the
- listing will be on following the directive, if the expression is
- false (zero) then the listing will be off. The directive #list
- switches the listing of all the files. The directive #ilist
- switches the listing only of the include files. The listing of the
- include files is off by default. This means that if you invoke
- PCMAC with the command line:
- PCMAC -l MAIN.ASM
- then you will get a listing on the screen, but no lines of files
- SUB1.ASM, SUB2.ASM and SUB3.ASM will appear. (See the example
- above!) The directives #list and #ilist have effect only if the
- compilation is on. It means that the lines:
- #if 0
- #list on
- #endif
- will not switch the listing on.
- Group No 3.
- #if expression
- This is a directive to switch the compilation off. If the
- expression is true (non zero) then the compilation remains on, if
- the expression is false (zero) then the compilation is turned off.
- However the expression will be evaluated if the compilation was
- on. In other words this directive opens a conditional block that
- has to be ended with the directive #endif. Such blocks can be
- nested as deep as you want.
- #ifdef identifier
- #ifndef identifier
- These directives are similar to the directive #if. They
- switch the compilation off according to the identifier. The
- directive #ifdef turns the compilation off if the identifier was
- not defined. The directive #ifndef turns the compilation off if
- the identifier was defined. These directives have the same effect
- as the lines:
- #if isdef(identifier)
- #if !isdef(identifier)
- #endif
- This directive closes a conditional block. If the the
- compilation was on before the block started it will be on again,
- and if it was off then it will be off.
- #else
- This directive splits up a conditional block. If the
- expression following the directive #if was true, then the
- compilation is turned off at the point of the directive else. If
- the expression was false then the compilation will be on again
- unless the whole conditional block is in a larger conditional
- block that switched off the compilation.
- #elsif expression
- This directive the mixture of #else and #if. The
- expression will be evaluated if the directive #if switched off the
- compilation, and the compilation switches on if the expression is
- true. Using this directive it is possible to separate more than
- two cases. To make it clear let us look at an example! The next
- program demonstrates how the directives of this group work.
- ;CONDEMO.ASM
- ;Program to demonstrate
- ;the directives
- ;#if
- ;#ifdef
- ;#ifndef
- ;#else
- ;#elsif
- ;#endif
- ;Some simple examples first:
- #if 1
- #message "The expression 1 is true"
- #endif
- #if 0
- #message "No matter what this string is,"
- #message "because it won't appear on the screen."
- #endif
- ;Some more complex
- var variable
- variable := 1
- #ifdef variable
- #message "The identifier variable is defined."
- #if variable
- #message "The value of variable is true."
- #else
- #message "The value of variable is false."
- #endif
- #else
- #message "The identifier variable is not defined."
- #endif
- ;Three different cases to separate
- variable := 3
- #if variable = 1
- #message "Variable = one."
- #elsif variable =2
- #message "Variable = two."
- #else
- #message "Variable greater than two."
- #endif
- ;End of file CONDEMO.ASM
- If we compile this program invoking PCMAC with the command line:
- PCMAC condemo.asm
- we will get the messages on the screen:
- MESSAGE **** The expression 1 is true
- MESSAGE **** The identifier variable is defined.
- MESSAGE **** The value of variable is true.
- MESSAGE **** Variable greater than two.
- MESSAGE **** The expression 1 is true
- MESSAGE **** The identifier variable is defined.
- MESSAGE **** The value of variable is true.
- MESSAGE **** Variable greater than two.
- We will get every messages twice because of the two compilation
- passes. Try to compile the file CONDEMO.ASM that is on the
- distribution disk.
- Group No 4.
- You can understand this group of directives if you are
- familiar with strings, and the way how PCMAC deals with strings.
- #octal
- This directive sets the radix of the string escape numbers
- to be eight. The numbers will be evaluated as octal numbers in
- string escape sequences, and any non octal character terminates
- them even the digits '8' and '9'. The radix for string escape
- numbers is octal by default, but it can be changed in later
- version of PCMAC. It is regarded to use explicitly octal or
- decimal in your program if you use string escape numbers.
- #decimal
- This directive sets the radix of the string escape numbers
- to be ten. The numbers will be evaluated as decimal numbers in
- string escape sequences.
- This is a good style of programming to use the directive
- decimal or octal at the start of every file, and to use after the
- #include or macros directives.
- Well, the best way is to use only one of them in every
- program.
- #char expression1,expression2
- This directive is useful when writing program for a
- machine that uses non ASCII character set. When PCMAC starts a
- pass fills up a table with numbers from 0 to 255. When a character
- appears in a string or in a character constans it represents a
- number according to the ASCII coding standard. PCMAC changes this
- value according to the table. If the character 'A' appears it
- represented by the code 65 in ASCII. PCMAC changes this code with
- the code that is in the table at the location 65. By default it is
- 65, because PCMAC sets the location i to hold the value i for any
- i=0 to 255.
- The directive #char changes the table. It evaluates the
- expressions and then changes the location pointed by the first one
- to hold the value of the second one. The order of this event is
- important. Let us look an example:
- ;CHARDEMO.ASM
- ;Demo program for the char directive
- DB "AAA\n\r"
- #char 'A','a'
- DB "AAA\n\r"
- #char 'A','A'
- DB "AAA\n\r"
- #char 65,'A'
- DB "AAA\n\r"
- #char 65,65
- DB "AAA\n\r"
- #char 'A','a'
- ;End of the file CHARDEMO.ASM
- If you compile this program with the command line:
- PCMAC CHARDEMO.ASM
- the resulting file CHARDEMO.TSK will be an ASCII file that you can
- type. Try to compile this assembly file, and then use the dos
- command:
- TYPE CHARDEMO.TSK
- You will see the following lines:
- AAA
- aaa
- aaa
- aaa
- AAA
- These bytes were generated by the assembly program above. Why?
- The first DB primitive generated three capital case 'A's
- and carriage return and new line. The second DB primitive generated
- three lower case 'a's, because the char directive changed the code
- of the character 'A' from 65 to 97. The second char directive does
- nothing. The value of the first expression is 97 at this time, and
- the table at the location 97 contains the value 97 because of the
- default setting. Therefore the third DB primitive generates the
- same code as the previous one. What does the next #char directive
- do? It changes the location 65 of the table to hold the code of
- the character 'A'. But this time it is 97 because of the first
- char directive. This directive does not change the table again and
- the fourth DB primitive generates three lower case 'a's again. The
- fourth char directive is clear how to interpret. The location 65
- changed to hold the value 65. The last DB primitive generates
- three capital case 'A's. The last char directive is only to
- demonstrate that PCMAC really fills up the table at the start of
- every pass. This is because you may wish to change the character
- set more than once in one file. An example when you have an
- assembly program that sends messages to the screen and to the
- printer as well. In this case your program will look something
- like this:
- ;Program skeleton for multiple character set usage
- START ;start of the executable code
- .
- .
- .
- Executable code
- LD A,'a' ; This is standard ASCII code
- .
- .
- .
- ;Character table setting for the screen
- #char 'a',1
- #char 'b',2
- .
- .
- .
- #char 'z',26
- ;messages to send to the screen
- scr_mes1 DB "message number one"
- scr_mes2 DB "message number two"
- .
- .
- .
- scr_mesN DB "message number many"
- ;Character table setting for the printer
- #char 'a',65
- #char 'b',66
- .
- .
- .
- #char 'z',90
- ;messages to send to the printer
- prt_mes1 DB "message number one"
- prt_mes2 DB "message number two"
- .
- .
- .
- prt_mesN DB "message number many"
- ;End of program skeleton
- The instruction LD A,'a' will load into the accumulator the value
- 97 because the default setting of the table is ASCII, and it is
- reloaded at the start of the second pass.
- You can redefine non printable code with the directive
- char but there is no use of it. All the escape sequences in the
- strings and in the character constants are treated as they are. So
- if you have a character constans '\65' in decimal mode then it
- will mean the value 65 no matter what kind of char directives
- preceded it. The other escape sequences as '\n' or '\r' will also
- not be changed.
- Remember that PCMAC refills the table at the start of the
- second pass! If you collect all the char directives in a file then
- you have to include it using the directive #include and not the
- directive macros!
- Group No 5.
- #dw hl or #dw lh
- #dd hl or #dd lh
- These directives change the byte and word generating order
- of the DW and DD primitives. By default DW generates a word in the
- way that the lower significant byte is the first and the higher
- significant byte is the second. The DD generates a doubleword in a
- similar way: the lower significant word is on the lower address
- and the higher significant word is on the higher address.
- This ordering method can be changed with this directives.
- The directive dw changes the ordering of the primitive DW. The
- letter pairs hl and lh means the order of the bytes. hl means:
- higher byte on the lower address lower byte on the higher address.
- lh means backward. The directive dd changes the word ordering in
- the same way. The meaning of the letter pairs are the same for
- words instead of bytes. These letter are not predefined labels or
- variables. They are keywords. You can use both as label or
- variable. You can find a demonstration program in the file
- ORDEMO.ASM. Here it is:
- ;ORDEMO.ASM
- ;Demo program for the dw and dd directives
- dw 1234h
- dd 12345678h
- #dw hl
- dw 1234h
- dd 12345678h
- #dd hl
- dw 1234h
- dd 12345678h
- #dw lh
- dw 1234h
- dd 12345678h
- #dd lh
- dw 1234h
- dd 12345678h
- ;End of the file ORDEMO.ASM
- The easiest way to see what codes were generated is to look at the
- list file. Here is the list:
- Versoft macro assembler.
- V 1.0
- Pass2
- + ;ORDEMO.ASM
- + ;Demo program for the dw and dd directives
- 0000 34 12 dw 1234h
- 0002 78 56 34 dd 12345678h
- 0005 12
- + #dw hl
- 0006 12 34 dw 1234h
- 0008 56 78 12 dd 12345678h
- 000B 34
- + #dd hl
- 000C 12 34 dw 1234h
- 000E 12 34 56 dd 12345678h
- 0011 78
- + #dw lh
- 0012 34 12 dw 1234h
- 0014 34 12 78 dd 12345678h
- 0017 56
- + #dd lh
- 0018 34 12 dw 1234h
- 001A 78 56 34 dd 12345678h
- 001D 12
- + ;End of the file ORDEMO.ASM
- Error : 0
- Warning : 0
- PCMAC gives a listing for all the passes. Here we presented only
- the listing of the second pass. You can see that the primitive DD
- generates the bytes in the same order between the words as
- primitive DW.
- Group No 6.
- You can understand this group of directives if you are
- familiar with macros, and the way how PCMAC deals with macros.
- #macarg expression
- #macnum expression
- A macro definition consists of syntax definition and macro
- body. You can and probably want to use the macro argumentum
- character and sometimes the macro numbering character in the macro
- body as normal characters. The macro argumentum character is the
- character #, the macro numbering character is the character @ by
- default. It can happen that some macro that you want to refer to
- in a macro body contains the # or the @ character. Assume that we
- have an instruction defined by the macro:
- macro("MOV ACC,#*",NUMBER)
- ;The macro body is not interesting here
- endm
- and we want to reference this instruction in the body of the
- following macro:
- ;Wrong macro definition
- macro("CLRJP *",LABEL)
- MOV ACC,#0
- JUMP #0
- endm
- PCMAC will think that you want to have the actual value of the
- argument in the first line. If we used this macro definition then
- PCMAC would extend it when reading the line
- CLRJP LABEL1
- to the lines:
- MOV ACC,LABEL1
- JUMP LABEL1
- This is actually not the wanted effect. What we want is:
- MOV ACC,#0
- JUMP LABEL1
- The correct definition for this can be:
- ;A possible solution
- #macarg '&'
- macro("CLRJP *",LABEL)
- MOV ACC,#0
- JUMP &0
- endm
- The directive #macarg changes the macro argument character to '&'.
- When PCMAC works up the macro definition it remembers the
- locations of the references to the macro argument and it stores
- this information. The later change of the macro argumentum
- character does not disturb PCMAC when it extends a macro. In
- other words: it is not interesting for PCMAC what the macro
- argumentum character was when the definition of the macro
- is finished. Another possibility for this macro definition is:
- ;Another possible solution
- macro("CLRJP *",LABEL)
- #macarg 0 ;any value not equal to '#'
- MOV ACC,#0
- #macarg '#'
- JUMP #0
- endm
- The macro numbering character is @, but using the directive macnum
- you can redefine it the same way as redefining the macro
- argumentum character.
- Be care when using any of the directive macnum and macarg
- together with the directive char. If you redefine the code of the
- character '&' and you use it as a macro argument or macro
- numbering character then writing the line
- #macarg '&'
- will set the macro argumentum character to a value you did not
- expect. The new value of the macro argumentum character will equal
- the new code of the character '&', because PCMAC changed the ASCII
- code evaluating the expression. However PCMAC does not change the
- ASCII code when it reads the source. The directive char influences
- only the string and character constants and not the source. If you
- write the lines:
- #char '&',')'
- macarg '&'
- then a reference to the first macro argumentum will be )0 instead
- of &0. The same holds for the macro numbering character.
- Group No 7.
- This group is useful for creating macros for high level
- assembly language. These features are not common in assemblers.
- Stack in assembly language is well known. These directives
- handle compile time stacks, and you must not confuse this with the
- conventional stacks. These stacks exists during the compilation
- and not during the program run. You can use these stacks to store
- 32 bit values during the compilation. You can push values onto the
- stack, you can drop a value from the stack you can open new stacks
- and close stack. A stack can contain many values. The value on the
- top of the stack is the value that was pushed to the top of the
- stack last. When you push a value to the top of the stack then the
- new value pushes the previous value one level down. Every value
- will get into one level deeper. When you pop a value from the
- stack then you remove the value from the top of the stack and
- every value that were pushed onto the stack will get one level
- higher. The top of the stack is the value of the highest level.
- The location, top of the stack, is often called TOS.
- #stack variable
- This directive opens a stack, and the number of the stack
- will be held by the variable. You can use this variable to refer
- the stack. Of course, you can transfer the identifier number of
- the stack into another variable and you can use the other variable
- to refer the stack. Onehundred stacks can be opened at a time. If
- you want to open more then onehundred stacks PCMAC will generate
- an error message.
- #pop expression
- This directive drops one value from the stack denoted by
- the value of the expression. It is possible to use any expression
- following the directive, but as a good programming style, it is
- regarded to use a single variable that the value was assigned to
- by the directive #stack. Using this directive you can not access
- the value that you drop from the stack. If you refer to a stack
- that was not opened or to a stack that is empty then PCMAC will
- generate an error message.
- #push expression1,expression2
- This directive pushes the value of the second expression
- to the stack that is identified by the value of the first
- expression. It is possible to use any expression following the
- directive, but as a good programming style, it is regarded to use
- a single variable that the value was assigned to by the directive
- stack. If you refer to a stack that was not opened PCMAC will
- generate an error message. You can push so many items onto a stack
- as many memory there are in your computer.
- #clostack expression
- This directive releases the stack identified by the value
- of the expression. It is possible to use any expression following
- the directive, but as a good programming style, it is regarded to
- use a single variable that the value was assigned to by the
- directive stack. When a stack has been closed it is emptied and is
- released and can be opened with the directive stack.
- Here we present some examples how to use these stacks
- handling directives. However, to read this text you have to be
- familiar a little bit with expressions.
- Let us define an instruction pair for the Z80 processor
- (that is an 8-bit machine), that creates an infinite loop. One can
- of course break this loop with jump instruction. We want to write:
- LOOP
- .
- .
- .
- body of the loop
- .
- .
- .
- ENDLOOP
- The simplest way is to use a variable that contains the address of
- the LOOP instruction, and make jump to that address in the body of
- the macro ENDLOOP. The definitions look like this:
- ;LOOP macro definition
- macro("LOOP")
- #ifndef loop_address
- var loop_address
- #endif
- loop_address := $
- endm
- ;ENDLOOP macro definition
- macro("ENDLOOP")
- JP loop_address
- endm
- This is very simple and we even needed not to use any compile time
- stack operation. The disadvantage of this solution is that we
- should not nest the loops. If we write a program that looks
- something like this:
- LOOP
- .
- LOOP
- .
- .
- body of the inner loop
- .
- .
- ENDLOOP
- .
- ENDLOOP
- then both of the ENLOOPs will jump back to the second LOOP. The
- solution is to open a stack by the directive stack, and push the
- jump-back address onto the stack. When closing a loop we can pop
- the address from the TOS. The macro definitions then look like
- this:
- ;LOOP macro definition nestable
- macro("LOOP")
- #ifndef loop_stack
- var loop_stack
- #stack loop_stack
- #endif
- #push loop_stack , $
- endm
- ;ENDLOOP macro definition nestable
- macro("ENDLOOP")
- JP pop(loop_stack)
- endm
- When the first macro is extended then it checks if the variable
- loop_stack is already defined or not. If not then it defines and
- opens a stack to hold the jump-back addresses. The rest of the
- macro pushes the address onto the stack. The macro of the
- instruction ENDLOOP generates an instruction that jumps to the
- address that was taken from the stack. Now you can see that this
- kind of stack has no relation to the usual machine stack. This
- stack stores values while compilation time, and helps you to keep
- tracing back information.
- Let us look a more sophisticated solution, when we want to
- implement the instruction BREAK that breaks the deepest loop. In
- this case when a BREAK instruction encounters we have to generate
- a jump to the end of the loop. The macro definitions will look
- like this:
- ;LOOP macro definition nestable with break
- macro("LOOP")
- #ifndef loop_stack
- var loop_stack,code_counter_store,address
- #stack loop_stack
- #endif
- #push loop_stack , NONADDRESS ;Any value that can not represent address
- #push loop_stack , $
- endm
- ;BREAK macro definition
- macro("BREAK")
- JP 0 ; We do not know the address now
- #push loop_stack , $-2 ;Store the address of
- ;the second byte of the instruction
- endm
- ;ENDLOOP macro definition that fills in the BREAK jumps
- macro("ENDLOOP")
- code_counter_store := $
- address := pop(loop_stack)
- #while tos(loop_stack) != NONADDRESS
- $ := address
- DW code_counter+3 ; 3 is the length of
- ; the jump-back instruction
- address := pop(loop_stack)
- #wend
- $ := code_counter_store
- JP address
- #pop loop_stack
- endm
- Well, the last macro is really sophisticated, and needs
- some explanation how it works. Let us look the list that was
- generated by PCMAC when it compiled the file STACK.ASM.
- Versoft macro assembler.
- V 1.0
- Pass1
- + ;STACK.ASM
- + ;Demonstration program for the usage of stack directives
- +
- FFFF NONADDRESS EQU -1 ;Any value that can not
- + ; represent address
- +
- Error : 0
- Warning : 0
- Start of the code : 0
- End of the code : 23
- Pass2
- + #list on
- + #endif
- +
- + LOOP ;* loop #1
- + LOOP ; * loop #2
- 0000 C3 00 00 BREAK
- 0003 C3 00 00 BREAK
- ENDLOOP ; * endloop #2
- 0004 09 00
- 0001 09 00
- 0006 C3 00 00
- 0009 C3 00 00 BREAK
- + LOOP ; * loop #3
- 000C C3 00 00 BREAK
- ENDLOOP ; * endloop #3
- 000D 12 00 C3
- 0010 0C 00
- 0012 C3 00 00 BREAK
- ENDLOOP ;* endloop #1
- 0013 18 00
- 000A 18 00
- 0015 C3 00 00
- + ;End of file STACK.ASM
- Error : 0
- Warning : 0
- You can see that the LOOP instructions do not generate
- code. It is shown by the sign '+' on the start of the line. This
- sign means that the line did not generate code although the
- compilation was not switched. If the compilation is switched off
- then a sing '-' appears on the start of the line. The instruction
- LOOP only stores the address in a stack. The instruction BREAK
- generates three bytes, but these bytes later have to be updated.
- The main code generation work is done by the instruction ENDLOOP.
- This macro pops out the addresses of the BREAK instructions, and
- fills up the address space of the jump instruction, and generates
- a jump instruction that jumps back to the start of the loop. The
- value NONADDRESS is to separate the nested stack space. It can be
- -1 because the processor Z80 we assumed in this example is an 8
- bit machine and -1 equals to 0FFFFFFFFh for PCMAC.
- Group No 8.
- This is a special group of directives that can only be
- used inside of a macro definition. These instruction make possible
- to define macros like ENDLOOP in the example of the previous
- group. However these macros could be neglected and even ENDLOOP
- could be defined recursively. The point to use these directives is
- to save up memory and speed up the compilation. Linear recursivity
- always needs a lot of memory, and a recursive macro needs a macro
- extension in every loop.
- #while expression
- #wend
- If these directive pairs surround a block of lines in a
- macro body then PCMAC will extend and repeat the lines so long as
- the expression is TRUE (non zero). If the expression becames FALSE
- (zero) then the lines between the directives will be skipped. If
- the expression is false at start then the lines will totaly be
- neglected and won't be extended at all. The expression is
- evaluated before the body of the loop.
- #repeat
- #until expression
- If these directives surround a block of lines in a macro
- body then PCMAC will extend and repeat the lines so long as the
- expression is false. The expression is evaluated after the
- extension of the loop body, so the lines between the directives
- will be extended at least once.
- These directives can be used only inside of a macro
- definition because PCMAC stores the macro bodies in the memory.
- When a loop directive encounters PCMAC has to track back to the
- start of it. It is not possible to track back in a file, or at
- least it would be very slow. The real power of these directives is
- the usage inside of a macro.
- Example:
- ;LOOP.ASM
- ;Demo program for looping directives
- macro("DEFS *",NUMERIC)
- #ifndef defs
- var defs
- #endif
- defs := #0
- #while defs>0
- DB 0
- defs := defs - 1
- #wend
- endm
- macro("SKIP *",NUMERIC)
- #ifndef skip
- var skip
- #endif
- skip := #0
- #repeat
- DB 0
- skip := skip - 1
- #until skip=0
- endm
- DEFS 10
- SKIP 10
- DEFS 0
- SKIP 0
- ;End of file LOOP.ASM
- This example can be found in the file LOOP.ASM on the
- distribution discette. You can try to compile it, but use the -l
- or the -m option and keep your hands over the control and the
- break (scroll lock) key. The DEFS 10 and the SKIP 10 instructions
- generate the same bytes: ten zeroes. The instruction DEFS 0
- generates nothing because the condition of the while loop is
- false. The instruction SKIP 0 generates a lot of zeroes, because
- it generates at least one byte. Having defined the byte it
- decreases the variable 'skip' which is now becames 0FFFFFFFFh.
- This instruction generates 100000000h bytes. So you should be very
- carefully using these instructions. In debugging your macros you
- can use the -m directive of the compiler.
- You could see in these examples in this chapter some macro
- definitions that used conditional directives, variable
- declarations. A macro can be extended many times and it has to
- define a variable only the first time. This is the reason for
- which we used the construction:
- #ifndef variable ;If the variable is not defined
- var variable ; then define the variable
- #endif
- We used this construction for the sake of simplicity. For larger
- macro libraries it is a better way to collect the macros into a
- file eg. MACROS.ASM and the variable and label declarations into
- another file eg. MACROS.H. Then the file MACROS.ASM can be
- compiled with the -K option of PCMAC and can be included with the
- lines
- #lib "MACROS.LIB"
- #macros "MACROS.H"
- In this case the macros do not check every time if they were
- extended first time or not. They only do the work they really have
- to, and the variables and labels are defined in the separated
- file. You can use the directive #macros, because the variable
- declarations are skipped in the second pass.
- Identifiers
- -----------
- An identifier is a character literal. The first letter can be
- an alpha character that are the letters from 'a' to 'z' and from
- 'A' to 'Z' or can be one of the letters '_', '$', '@'. The other
- letters of the identifier can be alpha character of numeric
- characters. The numeric characters are the digits: '0', '1', '2',
- '3', '4', '5', '6', '7', '8', '9'. The number of the letters in an
- identifier is not limited, but any label has to fit into a line.
- The maximal length of a line is 500 characters, because PCMAC uses
- a 500 bytes long buffer to store the lines. All the characters of
- an identifier are significant and PCMAC always treat lower and
- upper case letters in identifiers as different. Do not
- misunderstand the usage of the -c option!
- Labels
- ------
- A label identifies a constant of the range from 0 to
- 0FFFFFFFFh. A label in the source code is represented by an
- identifier. A label is defined when it stands on the left hand
- side of a line. You can assign a value to a label with the EQU
- primitive. If the line stands on the left hand side that contains
- not an EQU directive then the value of the predefined variable $
- is assigned to it. This value represents the address of the first
- byte that is generated according to the line. If the line does not
- generate code then the variable $ does not change and the value of
- it is not ambiguous. There can be assigned a value to a label only
- once while a compilation. The labels has to get usually their
- value in the first pass. If a value is assigned to a label with
- the EQU primitive then the expression on the right hand side has
- to be defined. It means that all the labels and variables that
- appear in the expression have to be defined. So you have to pay
- attention on the ordering of the EQU directives. You can not write
- into a file:
- A EQU B
- B EQU 12
- because B is not defined when it is referenced. You can say that
- easy to see that B will get the value 12 later, and PCMAC could
- assign the value to A when B is determined. Do not forget that
- there can be expression on the right of the EQU directive, and if
- PCMAC wanted to remember what value to assign to a label then it
- would have to store all the expressions that stand on EQUs and
- sort them after the first pass into an order they could be solved.
- Such a scheduler is not built into PCMAC to save up speed, program
- size and memory. You can easy sort the EQU primitives into the
- order:
- B EQU 12
- A EQU B
- It is usually not a problem programming in assembly language. Some
- programmers collect the EQU directives to the end of the source
- because when the assembler reaches the last code generating line
- it determined all the address dependent values and they can stand
- in expression.
- PCMAC does not skip the label definitions in the second
- pass. It checks if the label gets the same value or not. If it
- gets some other value then PCMAC gives an error message. It should
- not happen when you compile an errorless assembly program. It can
- happen only if you use the conditional directives referring to the
- predefined variable pass incorrectly.
- Variables
- ---------
- Variables identify values of the range from 0 to
- 0FFFFFFFFh. A variable is defined when it appears in a VAR
- primitive or when appears on the left hand side of an assignment
- instruction. PCMAC generates a warning message on the second case.
- The main difference between variables and labels is that
- the variables can have different values while the compilation.
- Their value can change. They are necessary in macros like the
- examples in the chapters above. Variables can appear in
- expressions. However variables can not be public, because they do
- not represent a value. They represent a lot of values as they
- change during the compilation. With the same assingment a variable
- can get different values in the first and in the second
- compilation. A very simple example is:
- VARIABLE := pass
- In this instruction the variable gets the value 1 in the first
- pass and gets the value 2 in the second pass. PCMAC does not care
- about it.
- Assignment Instruction
- ----------------------
- An assignment instruction assignes a value to a variable.
- A variable has to stand on the left hand side of the line. It is
- not necessary to start the name of the variable on the first
- column. The mnemonic of the assignment is the sign pair ':='. To
- the right of it an expression has to stand that must not contain
- undefined label or variable. Some examples:
- pass2 := pass = 2
- Having executed this instruction the variable pass2 will be true
- during the second pass and false during the first pass. Don't
- forget that the value of the variable pass2 will be false during
- the second pass so long as this instruction was not executed.
- BIT :=( defined(Z80) || defined(I8080) )*8
- + ( defined(I8086) || defined(M68000) )*16
- The variable BIT gets the value if one of the identifiers Z80 and
- I8080 is defined. The variable gets the value 16 if one of the
- identifiers I8086 and M68000 is defined. If one of the identifiers
- Z80 and I8080 and one of the identifiers I8086 and M68000 are
- defined at the same time then the variable BIT will get the value
- 24.
- Warning!!! This example is written into two lines because
- of the limits of the typesetting. In an assembly program it has to
- fit into one line.
- Predefined Labels and Variables
- -------------------------------
- The assembler has some variables that you need not define.
- They are defined before the assembler starts reading the source.
- These variables are different from the other variables because
- some of them change the value automatic. These variables:
- $ The dollar sign. This variable represents the current
- address of the code generator. This variable always
- contains the address where the next byte gets. If the
- source program changes the value of this variable then the
- next byte will be generated to the new address. See the
- definition of the ORG instruction in the Z80 macro library
- file. Here it is:
- macro("ORG *",NUMERIC)
- $ := #0
- endm
- The value of the variable $ is relocatable.
- pass The value of this variable is set to 1 before the first
- pass and is set to 2 before the second pass. You can
- assign a value to this variable but the value will be
- updated between the passes. The value is not relocatable.
- line This variable contains the number of the lines that were
- worked up in the actual file. This value can be redefined
- and it will be incremented finishing each line. The value
- is not relocatable.
- tline This variable contains the number of the lines that were
- worked up in the actual pass. This value can be redefined
- but it will be updated the same way as the value of the
- variable line. The value of this variable is not
- relocatable.
- on This is a variable that is defined by the assembler and
- the value of it is set to 1. This value is not
- relocatable.
- off This variable is defined by the assembler before the first
- pass and the value of it set to zero. The value is not
- relocatable.
- All the predefined variables can be assigned to, but it is
- not a good style to monkey with them. Do reassignment only when it
- is really necessary and increases the readability.
- Expressions
- -----------
- We were talking about expressions in the previous
- chapters, but until now we did not define what they are.
- An expression consists of labels, variables, functions,
- operators, brackets and strings. Every expression has a value that
- is a number between the interval from 0 to 0FFFFFFFFh and this
- value is relocatable or not relocatable. The relocation has
- meaning only in case when PCMAC generates object code instead of
- task file.
- Numbers
- -------
- The simplest expression is a number. A number can be
- written in decimal, hexadecimal, binary, octal or ASCII form. The
- first four type can be positive or negative.
- DECIMAL NUMBER
- A decimal is the sequence of decimal digits. These are 0,
- 1, 2, 3, 4, 5, 6, 7, 8, 9. A decimal number has no postfix but
- PCMAC can accept the 'd' or the 'D' postfix. A decimal number can
- be positive in the range from 0 to 4294967295, or can be negative
- in the range from -1 to -2147483648.
- Examples:
- 123 one-hundred and twenty three
- 2000 twenty hundred (two thousand)
- -1 minus one. This value is the same as
- 4294967295
- 33d thirty three with a 'd' decimal postfix
- HEXADECIMAL NUMBER
- A hexadecimal number is a sequence of hexadecimal digits.
- The hexadecimal digits are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C,
- D, E, F. The letters can be written in lower case as a, b, c, d,
- e, f. These letters stand for the values: 10, 11, 12, 13, 14 and
- 15. Hexadecimal numbers has to be followed by a letter 'H' or 'h'.
- This is called hexadecimal postfix. A hexadecimal number always
- has to start with a decimal digit. If eventually it started with
- some of the hexadecimal digits from A to F then you have to
- precede it with the digit 0. In order to get the value of a
- hexadecimal number you have to count the digits from right to left
- from zero up to the number of the digits minus one. You have to
- summ up the digits multiplying each with 16 powered by the
- position of the digit. Hexadecimal numbers are important when you
- want to see how many bytes are occupied by a number. One
- hexadecimal digit occupies exactly half byte that is four bits.
- Two digit hexadecimal numbers occupy exactly one byte, four digit
- hexadecimal numbers occupy exactly two bytes and so on.
- Examples:
- 1h one
- 0Fh fifteen. As you see it starts with the letter '0'.
- If we wrote Fh PCMAC would think that this is an
- identifier.
- 1Fh 1*16+15=31 in decimal form.
- 8E3aH 8*16*16*16+14*16*16+3*16+10=36410 You see that the
- case of the letters is not important in this case.
- BINARY NUMBERS
- Binary numbers consist of binary digits that are 0 and 1.
- Binary numbers are followed by the binary postfix that is the
- letter 'B' or 'b'. Each digit represents one bit. The calculation
- of the value of a binary number is almost the same as the
- calculation of hexadecimal numbers. The difference is that the
- digits have to be multiplied by the powers of 2 instead of 16.
- Binary numbers are important when we want to write a number in a
- form that shows which bit is set to one and which is zeroed.
- Examples:
- 1b one
- 10b two
- 10B also two
- 11B three
- 1010b ten
- OCTAL NUMBERS
- Octal numers are sequences of octal digits. These are 0,
- 1, 2, 3, 4, 5, 6 and 7. An octal number is followed with the octal
- postfix letter 'O' or 'o'. Do not mix it with the digit 0 that
- stands for the value zero. The reason why PCMAC knows octal
- numbers is that the first generation of computer programmers used
- to write numbers in octal form. Some of them still loves octal
- numbers. The value of an octal number can be calculated the same
- way as the value of a hexadecimal or binary number. Here the radix
- is eight, in other words you have to multiply the digits with the
- powers of 8.
- Examples:
- 1o one and not ten!
- 1O one and still not ten!( 1O is not the same as 10)
- 22o 2*8+2 = 18
- 25442o 2*8*8*8*8+5*8*8*8+4*8*8+4*8+2 = 1142
- ASCII NUMBERS
- Ascii numbers start with the character ' and end with it.
- There has to be at least one and at most four characters between.
- Each character represents its code. The code is usually the ASCII
- code, but it can be redefined with the #char directive. Each
- character code has to multiplied with the value 256 powered by the
- position of the character.
- There are special characters that could not appear in
- character constants. One of them is the ' sign. This is because
- that sign terminates the ascii number. If you want to include the
- character ' into an ascii number then you have to replace it with
- the character pair \'. Generally saying every character but digits
- and the letters t,n,r following the backslash \ character in an
- ascii number means itself and nothing else. So the backslash
- character has to be written \\. If some digits follow the
- backslash character then they are treated as octal or decimal
- numbers. They are treated as decimal numbers if the directive
- #decimal was used, and they are treated if the directive #octal
- was used or if none these directives were used. The escape
- sequence can be three digit long.
- Examples: (We assume that no #char directive was used.)
- '0' 48
- '00' 48*256+48=12336
- '0\0' 48*256+0 =12288
- '0\0000' 48*256*256+0*256+48=3145776
- This is because the escape sequence means zero
- and terminates after three digits. There is one
- more digit left that represents its ASCII code.
- 'A\19' 65*256+19=16659
- or
- 65*256*256+1*256+57=4260153
- depending on what the ASCII escape radix is. If
- the directive #decimal was used then the
- character '9' following the character '1' is
- member of the escape sequence and the value of
- the escape sequence is 19. If the directive
- #decimal was not used then the character '9' can
- not be member of the escape sequence because it
- is not an octal digit. In this case the escape
- sequence consists of two characters: the
- backslash character and the digit 1. The value of
- the escape sequence in this case is one and the
- character '9' represents its ASCII code.
- If the ASCII radix is octal and a digit terminates an escape
- sequence then PCMAC generates a warning message. There are some
- other special escape sequences for codes that often happen. The
- letter t,n,r following the backslash character means the values
- 9,10 and 13, respectively. These are special codes in the ASCII
- standard. The meaning of them are:
- '\t' tabulator character.
- '\n' new line character.
- '\r' carriage return character.
- All other characters have the same meaning as they stand after the
- character \ or not.
- ASCII character are useful when a number represents some
- character code in the assembly. If you see the assembly lines:
- LD A,65
- CALL 1601h
- you probably won't know what it means. If you can read the lines
- LD A,'A'
- CALL PRTCHAR
- you will find out the meaning. The program prints out the
- character 'A'. You need not search the ASCII code table that
- always is in your way but when you need it. There are more
- advantages of ASCII numbers. Assume that you calculated the code
- of the character for your machine in a wrong way and that is not
- 56 but 57. If you did not use character constants when you refer
- to the code of the letter A then you have to replace all the
- appearance of the digits 56 to 57. It is for sure that doing it by
- hand you will forget to change some of them. If you used some text
- editor command for automatic replace it will change the number
- 56738 to 57738. You should use ASCII numbers instead and change
- only the directive
- #char 'A' , 56
- to
- #char 'A' , 57.
- Let us turn back to expressions. Using numbers and
- operators we can build up compound expressions. If you wrote 1+1
- it would means the same as if you wrote 2. There are many
- operators PCMAC knows. Here is a table containing them:
- Precedence The operator Meaning
- --------------------------------------------------------------
- 1. || OR Logical or
- --------------------------------------------------------------
- 2. && AND Logical and
- --------------------------------------------------------------
- 3. | Bitwise or
- --------------------------------------------------------------
- 4. ^ Bitwise xor
- --------------------------------------------------------------
- 5. & Bitwise and
- --------------------------------------------------------------
- 6. <> Non equality
- == = Equality
- --------------------------------------------------------------
- 7. < Less than
- > Greater than
- <= Less or equal
- >= Greater or equal
- --------------------------------------------------------------
- 8. << SHL Shift left
- >> SHR Shift right
- --------------------------------------------------------------
- 9. + Addition
- - Substraction
- --------------------------------------------------------------
- 10. * Multiplication
- / Division
- % MOD Remainder
- --------------------------------------------------------------
- 11. ! NOT Logical not
- ~ Bitwise not
- - Unary minus
- + Unary plus
- --------------------------------------------------------------
- The higher the precedence of some operator is the earlier PCMAC
- performs it. Examine the expression:
- !12+5*3-7%4<<1 = 6*3 ^ 2 && +1 > 1+12
- PCMAC reduces this expression into a number in 11 steps. First it
- looks for unary operators. It finds the subexpressions !12 and +1.
- PCMAC replaces them by their value. !12 equals to zero and +1
- equals to one. The expression after the first step:
- 0+5*3-7%4<<1 = 6*3 ^ 2 && 1 > 1+12
- Now PCMAC looks for the operators multiplication, division and
- remainder. It finds the subexpressions 5*3, 7%4 and 6*3. The
- values for these are 15, 3, 18. Substituting:
- 0+15-3<<1 = 18 ^ 2 && 1 > 1+12
- PCMAC now looks for addition and substraction. There are some, so
- the expression gets the form:
- 12<<1 = 18 ^ 2 && 1 > 13
- The next step is to perform the operation 12<<1 that is 24:
- 24 = 18 ^ 2 && 1 > 13
- The next is to calculate the value 1 > 13. The value of it is
- FALSE. The numerical value of FALSE is zero.
- 24 = 18 ^ 2 && 0
- Now to perform the operation 24 = 18 that is FALSE==0.
- 0 ^ 2 && 0
- The next operation is the bitwise or 0^2=2
- 2 && 0
- The last step is to perform the operation && that is 1 if both
- arguments are not zero and the result is zero if any of them is
- zero. Finally the value of the expression is zero.
- 0
- To be honest the evaluation of an expression is not really so
- simple and later we will discuss it more detailed. Now we turn for
- the operations in detail.
- Logical OR || OR
- ----------
- This operator is written as two bars || or the word OR.
- The first version is common in the language C and can easy be read
- by C programmers. The second form is common in many languages and
- can easy be read by anyone. You can use any of them you wish. You
- can even mix them in an expression. The formal definition of this
- operation is:
- argument1 OR argument2
- The result of the operation is 1 if any of the arguments is
- non-zero. If argument1 is not zero then argument2 is not
- evaluated, so in this case argument2 can contain undefined or
- external identifiers. The line:
- !isdef(alpha) || alpha > 1
- will never cause the error: Undefined label in the expression!
- However argument2 must be syntactically correct.
- Logical AND && AND
- -----------
- This operator is written as two et signs && or the word
- AND. The first form is common in the language C, the second one is
- common in any other language. You can use any of them you wish.
- You can even mix them in an expression. The formal definition of
- this operation is:
- argument1 AND argument2
- The result of this operation is 1 if both of the argumentums are
- non-zero. If argument1 is zero then argument2 is not evaluated.
- The line:
- isdef(alpha) && alpha > 1
- will never cause the error: Undefined label in the expression!
- However argument2 must be syntactically correct.
- This kind of evaluation when the logical arguments are
- evaluated if it is necessary is usually called short cut
- evaluation.
- Bitwise OR |
- ----------
- This operator is written as one bar |. The formal
- definition of this operation is:
- argument1 | argument2
- The result of this operator is the number what is created setting
- all the bits that are in a position for which the bit of argument1
- or argument2 is set. So 2|1 is 3, 3|1 is also 3 and 2|4 is 6.
- Bitwise xor ^
- -----------
- This operator is denoted by the character caret ^. This is
- usually on your keyboard over the number 6 on the same key. The
- formal definition of this operation is:
- argument1 ^ argument2
- The result of this operation is the number that we get setting all
- the bits that are in a position in which one and only one of the
- bits of argument1 and argument2 is set.
- Bitwise and &
- -----------
- This operator is denoted by the character &. This is
- usually on your keyboard over the number 7. The formal definition
- of this operation is:
- argument1 & argument2
- The result of this operator is the number that we get setting all
- the bits that are in a position for which both bits of argument1
- and argument2 are set.
- Nonequality, equality = ==, <>
- ---------------------
- The equality operator has to form. One is a single =
- character. The other one is a double = that is ==. Any of them can
- be used. The inequality operator is <>. The formal definition is:
- argument1 = argument2
- is 1 if argument1 has the same value as argument2 and zero
- otherwise. The inequality
- argument1 <> argument2
- is the opposite of equality. It is 1 if the arguments have
- different values and 0 if they are the same.
- Comparing operators <, >, <=, >=
- -------------------
- These operators are <, >, <= and >=. The formal
- definitions are:
- argument1 < argument 2
- It is 1 if the value of argument1 is less than the value of
- argument2 and is 0 otherwise.
- argument1 <= argument 2
- It is 1 if argument1 is less or equal to argument2 and is 0
- otherwise.
- argument1 >= argument 2
- It is 1 if argument2 is less or equal to argument1 and is 0
- otherwise.
- argument1 > argument 2
- It is 1 if the value of argument2 is less than the value of
- argument1 and is 0 otherwise.
- Shift operators >> SHR, << SHL
- ---------------
- These operators are denoted the same as they are in C
- language. The lexeme << means the shift left, the lexeme >> means
- the sift right. The words SHL and SHR can also be used. The formal
- definitions are:
- argument1 << argument2
- The result of the operation is the value of the first argument
- multiplied by 2 powered by argument2. This can be interpreted as
- the binary form of argument1 shifted to the left argument2 times.
- argument1 >> argument2
- The result of the operation is the value of argument1 divided by 2
- powered by argument2. Only the integer part is taken. This
- operation can be interpreted as if the binary form of argument1
- was shifted to the right argument2 times.
- Addition, Substraction +, -
- ----------------------
- The sign of these operations is + and -. The operation +
- adds argument1 and argument2, the operator - substracts argument2
- from argument1. The formal definitions are:
- argument1 + argument2
- argument1 - argument2
- Multiplication, Division, Remainder *, /, % MOD
- -----------------------------------
- The operator * generates the argument1 times argument2 for
- argument1 * argument2.
- The operator / generates argument1 divided by argument2 and
- truncating to be integer.
- argument1 / argumnet2
- The operator % creates the remainder of argument1 divided by
- argument2.
- argument1 % argument2
- The operator % has another form, the word MOD. Any of these can be
- used.
- Unary operators ! NOT , ~ , - , +
- ---------------
- These operators are unary. It means that they have only
- one argument. The formal definitions of these operations are:
- ! argument or NOT argument
- ~argument
- -argument
- +argument
- The result of the operation Logical Not is 1 if the
- argument is zero. The result is zero if the argument is not zero.
- The result of the Bitwise Not is the number that we get
- setting all the bits that are cleared in the argument and clearing
- all the bits that are set in the argument.
- The result of the operation unary minus is the opposite of
- the argument.
- The result of the operation unary plus is the value of the
- argument itself.
- The last operator seems useless. However it is not. You
- can use brackets to change the order of the evaluation. For this
- purpose you can use the () brackets and the [] brackets. This is
- because some assembly language uses the () brackets to refer
- memory location, other uses the [] brackets for it. If your
- assembly uses one of these for that purpose then use the other one
- to close the subexpressions. It is the easiest way not to confuse
- the different brackets. The only problem is that PCMAC does not
- know which type of brackets is used in expressions and which type
- of brackets is used to refer memory location. How can PCMAC decide
- what the instruction
- LD A,(63)
- means. At first glance it seems to be an instruction that loads
- the value of the memory location 63 into the register A. At the
- same time this instruction could mean to load the value 63 into
- the register A. This is because the string '(63)' can be
- interpreted as an expression in brackets, or an expression without
- brackets because the brackets can be part of the expression.
- The solution is that PCMAC does not allow you to start an
- expression with bracket. If you really have an expression that has
- to start with bracket then put + sign before it. An example is:
- (#0<<3)*(#1>>1)
- This line can appear in a macro body. You can not sort the
- expression to start with no bracket. You have to write:
- +(#0<<3)*(#1>>1)
- The + sign will tell PCMAC that this is an expression.
- Sometimes very complex expressions can appear and it
- happens that the number of the closing brackets is the same but
- they are not paired the way you wanted. PCMAC helps to maintain
- sophisticated expression by its rigour. PCMAC does not allow you
- to pair a ( bracket with a ] one or vice versa. You should use the
- same type of brackets. So you can write:
- +[#0<<3]*(#1>>1) ,
- but you are not allowed to write
- +[#0<<3)*(#1>>1] .
- Some words more about how PCMAC evaluates an expression.
- PCMAC always evaluates an expression from the left to the right,
- and if an operation can be executed it executes immediately. When
- PCMAC sees the expression:
- 6*3+5*2
- when reaches the sign + it knows that the multiplication can be
- done. No matter what follows the + sign. The subexpression
- 6*3+...
- is equivalent to the expression
- 18+...
- The three dots mean that the expression continues. If the left
- argument of an operator determines the result then PCMAC does not
- evaluate the right argument. However the right argument must be
- syntactically correct because PCMAC has to parse it to know where
- it ends.
- Expressions can contain some functions. These are:
- isdef( identifier ) The result of this function is 1 if the
- identifier was defined and 0 otherwise.
- strlen( string ) The result of this function is the length of
- the string. This is the number of the bytes
- that would be generated if the string stood
- after a DB primitive.
- pop( expression ) The value of the function is the value of the
- top element of the stack that is denoted by
- the expression. As a side effect this
- function also removes the element from the
- given stack.
- tos( expression ) This function returns the same value as pop,
- that is the top value of the stack given but
- it does not remove the top element of the
- stack.
- isreloc(expression) The result of the function is 1 if the
- expression is relocatable and 0 otherwise.
- doreloc(expression) The result of this function is the same as
- the value of the expression. The difference
- is that this value is relocatable no matter
- if the value of the expression was or not
- relocatable.
- doureloc(expression) The result of this function is the same as
- the value of the expression. The difference
- is that this value is not relocatable no
- matter if the value of the expression was or
- not relocatable.
- Relocation
- ----------
- When writing a large program it is good to split up into
- modules and link them together. Assume a large program that
- consists of the modules MAIN.ASM and PART.ASM. We have to compile
- these files with the command lines:
- PCMAC -o MAIN.ASM
- and
- PCMAC -o PART.ASM
- The resulting files will be:
- MAIN.O
- and
- PART.O.
- To generate executable code we have to link them together with
- the command line:
- LINK MAIN.O PART.O
- The resulting file MAIN.TSK is executable fix code. When we wrote
- the assembly lines PART.ASM we did not know where this part of the
- program will start in the memory. It is not a problem. You can say
- any address. PCMAC remembers the addresses and when you link
- programs PCMAC relocates the program automatic. The address of the
- first byte of the program PART is the length of the program MAIN.
- PCMAC links them together.
- MAIN +-----------------------+START
- | |
- | MAIN |
- | |END
- PART +-----------------------+START
- | |
- | PART |
- | |END
- +-----------------------+
- Relocation means that all the words and double words that refer to
- addresses that varies with the start of the module are corrected.
- If we wrote an assembly program that starts at the address 100H
- and it is linked and gets to the location 101H then all the jump
- instructions and other instructions that refer to memory location
- in the program will be corrected adding one to them.
- The predefined variable $ has relocatable value. An
- expression has relocatable value if it is a relocatable variable
- or label, or if it is the sum of a relocatable and a
- nonrelocatable value. The difference of two relocatable value is
- not relocatable. You need not care the ordering of an expression.
- There won't be difference. If all the variables A, B and C are
- relocatable, then the following expressions are all relocatable:
- A-C+B
- A+B-C
- B-C+A
- The result of any other operation is nonrelocatable no matter what
- the arguments were. The exceptions is the function
- doreloc(expression) that generates always relocatable value.
- Strings
- -------
- Strings can appear after the DB primitive in expressions
- and as actual macro argument. A string starts and ends with the
- sign ". There can be any character between them with the
- exceptions that were discussed in the chapter of ASCII numbers.
- The sign ' can appear in a string without \ but the " has to be
- preceded with the backslash character. The \n,\t,\r escape
- sequences can be used, and the three-digit octal or decimal escape
- sequences work as well. The directives #decimal and #octal do for
- the strings as well.
- Macro definitions
- -----------------
- PCMAC could not do without macros. Macros are used to
- define the assembly language. You can read and study the files
- Z80.MAC and EZ80.MAC that are on the distribution disk to avoid
- reading this chapter. However this contains detailed information
- that you can not find out only reading the files.
- The syntax definition of macros
- -------------------------------
- Each macro definitio contains two parts. The first part is
- the syntax definition. This is one line and looks like this:
- macro(syntax string , symbolic constans list)
- The keyword macro tells PCMAC that the line contains a macro
- definition. The string that was called syntax string tells PCMAC
- how the main syntax of the macro looks like. This string is
- special. The escape sequences are treated other than ordirary
- strings, and the character asterisk has special meaning. An
- assembly line is treated as a macro if it matches the syntax
- string. If we have the syntax string "LD A , ( H L )" it can be
- matched by any of the lines:
- LD A,(HL)
- LD A,(H L) ;Comment
- label LD A ,(HL)
- LDA,(HL)
- But the line
- L D A,(HL)
- does not match the definition. You can see that labels, comments,
- trailing and leading spaces do not disturb PCMAC. A line matches
- the syntax string if cutting off these parts all the characters
- matches. The space character is a special one. In the syntax
- definition a space works as a hundred. One space matches zero, one
- or more spaces. If you want to force PCMAC to look for exactly one
- space after the keyword LD you have to use the syntax definition:
- "LD\ A , ( H L )" The character pair backslash-space matches
- exactly one space. In this case only the first and the labeled
- match the syntax definition. Let us require at least one space
- after the keyword LD using the syntax definition: "LD\ A , ( H L
- )". After the backslash there are two spaces. The first one
- matches exactly one space and the second one matches zero or more.
- Generally saying all the characters but space backslash and
- asterisk matches the same character. Space matches zero or more
- spaces (tabulators as well). Asterisk matches a symbolic constans
- that has to be defined earlier. The backslash character is the
- escape character in the syntax string. Any character following the
- backslash character matches the same character and there is no
- exception. So \\ matches one \ character. If we look at the
- previous example we will see that the macro matches only the
- instruction that loads the memory location pointed by HL to the
- accumulator. However the value of that location can be loaded into
- any register that the Z80 has. So we have to define this
- instruction in the following way:
- const _SS := (B,C,D,E,H,L,(HL\),A)
- macro("LD *,(HL)",_SS)
- The part of the syntax definition that was called symbolic
- constans list now contains only one symbolic constans, _SS. The
- asterisk in the syntax string can match any element of the
- symbolic constans _SS. These are the letters B,C,E,H,L,A and the
- four letter character literal (HL). The definition of the symbolic
- constans is
- const identifier := ( literal list )
- The keyword const tells PCMAC that the line contains a symbolic
- constant definition. The identifier is used to identify the
- constant. The literal list is a list of the elements of the
- symbolic constant. Every element is a character sequence that must
- not contain comma(,), backslash (\) and closing bracket ()). If
- some has to contain any of these then the character has to be
- preceded with a backslash character, as you saw in the example.
- The elements are separated by commas. The symbolic constant list
- has to contain so many symbolic constant name as many asterisk
- there are in the syntax string (not counting the asterisks
- following backslashes). The first asterisk will match the
- members of the first symbolic constant in the list, the second
- asterisk will match those of the second one and so on.
- What Are Symbolic Constants
- ---------------------------
- The symbolic constants are those parts of the syntax
- definition that are not stable, that can vary. As you see in the
- previous example there was a place in the line where not only one
- character could stand but a great number of different literals.
- The literals have to be defined earlier. There are three
- predefined symbolic constants: STRING, NUMERIC, LABEL. The
- asterisks that are related to these constants will match a string,
- any expression and any identifier, respectively.
- Referencing a Macro
- -------------------
- Referencing a macro is the easiest to do. You only have to
- write a line that matches a macro. If you did and PCMAC finds the
- line then PCMAC replaces it with the lines of the macro body.
- These lines stand between the macro syntax definition and the
- keyword endm. These lines can contain macro referencing lines, but
- no macro definitions. So macros can be nested but macro
- definitions can not.
- When a macro matches a line PCMAC collects the actual
- value of the symbolic constants, and replaces the references to
- them in the macro body. A special character # is used to reference
- the argumentums. #0 refers to the first argumentum, #1 refers to
- the second one and so on. (The character # can be redefined by the
- directive #macarg.) If we have the macro definition:
- macro("LD\ *,*",_SS,_SS)
- #if #0 == 6 && #1 == 6
- #error "LD (HL),(HL) is invalid."
- #endif
- DB 40h+(#0<<3)+#1
- endm
- then writing the line
- LD A,B
- is the same as we wrote the lines:
- #if 7 == 6 && 0 == 6
- #error "LD (HL),(HL) is invalid."
- #endif
- DB 40h+(7<<3)+0
- You can see that the user defined symbolic constants are replaced
- by the position number of the literal that stands at the place of
- the argument. This position number starts with zero and not 1.
- This is more comfortable in many cases. This makes you easy to
- define assembly instructions. According to this in the example:
- const _SS := (B,C,D,E,H,L,(HL\),A)
- the value of B is zero, the value of C is 1, ... , the value of A
- is 7. The #nn references that refer to a STRING type argument will
- be replaced by the string itself. If a #nn references a NUMBERIC
- type argument then it will be replaced by the actual value of the
- expression. If a #nn references a LABEL type argument then it will
- be replaced by the label itself instead of the value of the label.
- It makes you possible to define macros that can accept external
- labels. Here are three examples:
- 1.)
- macro("JP *",LABEL)
- DB 0c3H
- DW #0
- endm
- The line
- JP J1
- will be replaced by
- DB 0c3h
- DW J1 .
- 2.)
- macro("ASCII *",STRING)
- DB strlen(#0),#0
- endm
- The line
- ASCII "Udvozlet mindenkinek."
- will be replaced by the line:
- DB strlen("Udvozlet mindenkinek."),"Udvozlet mindenkinek."
- 3.)
- macro("JP *",NUMERIC)
- DB 0c3h
- DW #0
- endm
- The line
- JP J1
- will be replaced by the lines
- DB 0c3h
- DW 1601
- assuming that the value of the label J1 is 1601.
- To examine how macros are extended you can use the -m option
- of PCMAC. This option forces PCMAC to list all the lines, not only
- the source but every lines that were generated extending a macro.
- There is another special character that is extended in the
- macro body, not only the # character. This character is the @. If
- this character appears anywhere but inside of a string or
- character constant in the macro body it is treated as macro
- numbering character. When extending a macro this character will be
- replaced by the decimal form of the number that shows how many
- times the actual macro was extended in the pass. If there are two
- of these characters close to each other then they will be replaced
- by the decimal form of the number that shows how many macro
- extension were in the actual pass. You can examine how it works
- using the -m option of the assembler. This character also can be
- redefined with the directive #macnum.
- Some Fine Points of Macros
- --------------------------
- Assume that you want to use the jump instruction referring
- to external labels, but sometimes you want to specify the target
- address using expressions. What to do? The macro definition
- macro("JP *",NUMERIC)
- won't accept external variable and the definition
- macro("JP *",LABEL)
- won't accept sophisticated expressions. The solution is to use
- both. You have to define two different jump instruction in the
- same macro definition system.
- macro("JP *",LABEL)
- db 0c3h
- dw #0
- endm
- macro("JP *",NUMERIC)
- db 0c3h
- dw #0
- endm
- The body of these macros obviously is the same. It is important to
- order of the definitions. PCMAC stores the macro definitions in a
- list in the same order as they were defined. If you have the
- macros:
- macro("JP *",NUMERIC)
- db 0c3h
- dw #0
- endm
- macro("JP *",LABEL)
- db 0c3h
- dw #0
- endm
- then writing the line
- JP EXTERNAL_LABEL
- will cause error message if EXTERNAL_LABEL is really an external
- label. This is because the first macro matches the line, and
- accepts it. Using this ordering all the lines that could be
- accepted by the second definition will be accepted by the first
- one and so the second one plays no role.
- Sometimes ordering is not so important. If you have the
- macro definitions:
- macro("JP *",NUMERIC)
- DB 0c3h
- DW #0
- endm
- macro("JP RESET")
- DB 0c3h
- DW 0
- endm
- then the line
- JP RESET
- will be accepted always by the macro definition that is fully
- static. This is because PCMAC tries to accept a line in two pass.
- First it only tries the macro definitions that have no NUMERIC
- argument, and tries these only if the first try was unsuccessful.
- Some macro definitions are unmatchable. This is the case
- if a macro definition ends with a '\ ' forced space that matches
- exactly one space. No line will end with one space because PCMAC
- cuts off the trailing spaces before trying to interpret as macro.
- Some simple cases are discovered by PCMAC and it generates a
- warning message. However the problem to discover unmatchable
- syntax definitions is very difficult, and PCMAC sometimes thinks a
- syntax definition to be matchable when it is not. Some example is:
- macro("Artificial *+(3)",NUMERIC)
- endm
- This macro will never be matched. If we want to refer to it a line
- like
- Artificial 1+(3)
- PCMAC will think that all the characters '1+(3)' belong to the
- expression and won't find the characters '+(3)'.
- Command Line Options
- --------------------
- If you start PCMAC with the command line that contains
- only the name of the program, that is PCMAC if you did not rename
- it, then PCMAC will print out the following lines:
- Macro assembler (C) Versoft Ltd. Hungary.
- Usage: pcmac ['-' options ] filename
- Options:
- l list on
- ln&name listfilename+list on
- m list macro extension(+list).
- mn&name listfilename+macro listing+listing.
- s symbol table
- c case sensitivity
- n&outfilename
- K to make library.
- o generate object.
- t don't care publics and externals.
- h generate header file.
- v version number.
- & means: write the name without any space!
- A command line that invokes PCMAC has to start with its name. You
- can freely rename the file with the standard DOS command rename.
- This name tells the DOS what program to start. The rest of the
- line is read by the program. PCMAC parses the rest of the command
- line and every argument starting with the sign - is treated as
- option. Options can appear anywhere on the line. The file name
- that appears on the line is the file that contains the source of
- the assembly program. The full file name has to be written because
- PCMAC makes no default extension. If no file names present in the
- -n option then PCMAC generates a name for the output. It cuts off
- the extension of the name of the input file and adds the extension
- .o if generates object file or .tsk if generates task file or the
- extension .lib if the option -K was given or the extension .h if
- the option -h was given. If the extension of the input file is .o
- and the option -o was given then PCMAC gives the .q extension
- under MSDOS and .O under UNIX. If another file name presents on
- the command line in the option -n then that is taken as output
- file name. Let us go through the options in details:
- l list on
- If this option is given then the assembler generates list
- of the compilation to the screen.
- ln&name listfilename+list on
- If this option is given then PCMAC generates list of the
- compilation into the file
- m list macro extension(+list).
- If this option is given then PCMAC generates a list that
- contains each line that is compiled. If you use this
- option then you can see in the list file how the macros
- are extended.
- mn&name listfilename+macro listing+listing.
- This option is similar to the -ln option. You can specify
- a listing file. PCMAC will generate a list of the
- compilation to the specified list file and the listing
- will contain the macro extensions.
- s symbol table
- If you use this option then PCMAC will generate a
- symbol table finishing the second pass. The symbol table
- listing is highly readable and appears on the end of the
- list file.
- c case sensitivity
- By default PCMAC does not care the case of letters in the
- macro definitions, so any character matches it lower case
- or upper case pair. If you specify this option then PCMAC
- won't treat upper and lower case letters in macro
- definitions as same.
- n&outfilename
- You can use this option to specify the name of the file to
- be generated.
- K to make library.
- You can use this option to generate a macro library file.
- Such a file usually has the extension .lib and can be
- included with the directive #lib. Only such files can be
- compiled with this option that do not contain code
- generation instructions. The generated macro library file
- will contain the macro definitions and the byte and word
- ordering, but will not contain any variable or label
- declaration.
- o generate object.
- Using this option PCMAC will generate object code. The
- generated object code will contain the code, information
- how to link it to other object files, which code fragments
- to relocate and so on.
- t don't care publics and externals.
- Sometimes you want to compile a file that is usually
- compiled using the -o option. If you don't use the -o
- option then PCMAC will generate error message when a
- public or extern primitive appears. This option supresses
- this messages.
- h generate header file.
- If you use this option then PCMAC will stop after the
- first pass and generates a readable text file that
- contains EQU primitives that assigns the values to the
- labels that appeared in the source. Using this option you
- can avoid using the linker if you really want to. However
- using the linker is much powerful.
- v version number.
- If you specified this option then PCMAC would neglect all
- other options and filename, if any, and writes out a short
- text on the original owner of the copy. If this text names
- any person then your copy is a pirate one. Some Hungarian
- men got copies for debugging purposes. All those copies
- contain the name of the owner and it is written out for
- the -v option. What is more: these copies are not the last
- versions of the assembler, these copies do not work
- properly and there is no guarantee that such a copy will
- not damage your files or hardware. If you have such a copy
- connect the firm ???????????????????.
- The Linker
- ----------
- The linker is a separated program that links the object
- files were generated by PCMAC to task file. You can start the
- linker with the command line:
- link
- If no argument is given then the linker prints out a sort
- remainder about its usage:
- Usage: link [options] input_file_name_list
- Options: -B[x]nnnn base address. (if x then in hex.)
- n&name change default (a.tsk) outfilename
- w reverse word order.
- d reverse long word order.
- The & means: write the name without space.
- The word link is the name of the file containing the linker. You
- can change it if you want with the standard DOS command rename.
- Many different linkers have the name: link. You can choose a name
- that is good for you as pcmaclnk or linkpcmc or any else. The
- first word on the command line has to be the name of the file
- containing the program. The rest of the line is read by the linker
- itself. Every argument that starts with the character - is treated
- option. The arguments that start with some character that is not -
- is treated as file name that the linker has to read and link to
- the others. The PCMAC linker has much less options than the
- assembler. The most important option is the -B option. Using this
- option you can specify the base address of the task code. This is
- the address where you want to load the program. The linker will
- relocate the addresses that are relocatable in the object file so
- that your program will start on the address you specified with the
- option -B. This option must contain a number. If you have an
- object file named MYFIRST.o then using the command line:
- link MYFIRST.o -B32000
- will generate a task file called a.tsk that contains code that you
- can load into your target machine to the address 32000. You can
- specify the base address in hexadecimal form. In such a case you
- have to use the option -Bx. So the command line:
- link MYFIRST.o -Bx7d00
- has the same effect as the previous one.
- The linker has to know how to treat the words and the
- double words. If the the words contain the bytes in normal order,
- that is lower address lower significant byte, then you should not
- use the -w option. This option says that the words have to be
- dealt with in reverse order. This is the case for the code of the
- MOTOROLA processors. The option -d says that the double words
- contain the words in reverse order.
- The default file name for the generated code is a.tsk. If
- you want to change this then you have to use the -n option. You
- can use it the same way as the option -n of the assembler PCMAC.
- The Format of the Object Code
- -----------------------------
- This chapter is not necesary to be read for using PCMAC
- assembler and linker. This chapter is included here to save up
- time of heavy hackers who would investigate the format of the
- object format of PCMAC. By the way, it is not secret. You can
- write your own programs that generate PCMAC object format file,
- and you can link them together with the PCMAC linker. If you do so
- then do not depend on features that you found scanning the
- generated object files but which are not declared here. Later
- versions of PCMAC may generate different format. In the current
- version all the public and external label declarations are at the
- end of the file. This feature is NOT declared and later can be
- changed.
- The format of the PCMAC object code is different to the
- standard Microsoft object format. This is because:
- 1.) When the development of PCMAC stated the developers had no
- information on that format.
- 2.) The Microsoft object format is too sophisticated. Using that
- format would have caused a slower assembler and linker.
- Here we present the definition of the format of the PCMAC
- object file. All the codes are written in hexadecimal form.
- PCMAC object file starts with the bytes 55 and AA. If
- these bytes are missing then the linker stops with error. These
- bytes make possible for the linker to find out if the file is not
- a PCMAC object file with the probability 99.99847412%. Following
- this magic word the object file consists of blocks. Every block
- starts with an identifier byte. These are:
- 81 CODE
- 82 RELOC
- 83 PUB
- 84 EXTDEF
- 85 EXTREF
- The names here present as reference names. The developers of PCMAC
- used these names. Following this byte there are two bytes
- containing the length of the body of the block. The body is follow
- by one byte check sum. The format of the body of a block depends
- on the type of the block. Here is the format of the bodies and
- some comment on their contents.
- 81 CODE 4ADDRESS 1NRofBYTES bytes
- These blocks contain generated code. The first four bytes of
- contains the address where the code has to be put. This
- address will be modified by the linker. The following byte
- contains the number of the bytes that are in the body. The
- rest of the block body is the list of the bytes.
- 82 RELOC 1NRofITEMS ITEMS( 1SIZE[0W F0D] 4ADDRESS)
- These block bodies contain the information about the
- addresses that have to be relocated. The first byte of the
- body is the number of the items that are in the block. The
- rest of the block body is the items. Every item is five bytes.
- The first byte is zero if the address points to a word to
- relocate and contains F0 if the address points to a double
- word to relocate. The last four bytes of the item presents the
- address.
- 83 PUB 1(0=NREL F0=REL) name \0 4VALUE
- These block define the public symbols that are defined as
- external symbols in other files. These symbols can be
- referenced in other files. The first byte of the block body is
- zero if the value of the symbol is absolute and is F0 if the
- value of the symbol is relocatable. This byte is followed by
- the identifier of the symbol. Any character sequence that
- contains no zero byte and is shorter than 100 bytes is an
- identifier for the PCMAC linker. The name is terminated with a
- zero byte. The last four byte of the block body is the value
- of the symbol.
- 84 EXTDEF name \0 2IDTFNUM
- These blocks define an external symbol. The body starts with
- the the name of the external symbol. The name has to be
- shorter than 100 bytes and must be terminated by a zero byte.
- The last two bytes of the block body contain the identifying
- number of the symbol. This identifying number is used in the
- blocks EXTREF. Such an identifying number is unique within one
- object file. Different object files for different external
- identifiers can have the same identifying number and different
- object files for the same external identifier can have
- different identifying number.
- 85 EXTREF 1NRofITEMS ITEMS(2IDTFNUM 1TYPE[
- 1BYTE 2WORD 4DWORD feRBYTE fdRWORD fbRDWORD] 4ADDRESS)
- These blocks contain the information of the holes of the
- code that have to be filled up with the values of the global
- symbols. The first byte contains the number of the items of
- the block. Every item is seven bytes long. The first two bytes
- contain the identifying number that has to be defined in a
- EXTDEF block. The next byte is the type of the location where
- the address points to. This byte can be:
- 01 The value has to fit into a byte.
- 02 The value has to fit into a word.
- 04 The value has to fit into a double word.
- FE The value has to be converted relative
- and fit into a byte.
- FD The value has to be converted relative
- and fit into a word.
- FB The value has to be converted relative
- and fit into a double word.
- The last four bytes of the item contain the address of the value.
- Error messages of the assembler
- -------------------------------
- The assembler handles five different type of errors. These types
- are:
- MESSAGE
- WARNING
- NORMAL
- FATAL
- INTERNAL
- A MESSAGE type error message appears in the list, that is
- usually the screen, when the assembly program contains some
- #message directive. This is not really an error. It is a simle
- message. The assembler writes it out and forgets all about it. The
- assembler itself does not generate such type of messages.
- A WARNING type message warns the user if he made some mistake
- which is not too serious and the assembler can correct it. However
- in many cases it is very useful to pay attention to the warning
- messages.
- A NORMAL type error message appears in the list if PCMAC finds
- some error in the source that is too serious to decide how to
- solve it. After such an error message PCMAC continues the
- compilation but it is only for the discovery of later errors.
- PCMAC does not generate code if any NORMAL type error message
- appeared. PCMAC starts the second pass even if there were some
- NORMAL type error messages in the first pass, and can happen that
- there is no such error in the second pass. In this case PCMAC
- warns you at the end of the list that there were error messages in
- the first pass.
- A FATAL type error message appears if PCMAC finds some error
- that prevents PCMAC to continue the compilation. If such an error
- encounters PCMAC stops the compilation immediately.
- An INTERNAL type error appearance means that there is some error
- in the assembler itself. You can do nothing to recover it but
- report it to the firm who released your version of PCMAC and to
- wait for the next release. However you can try to change your
- assembly file in some way but there is no guarantee that you
- succeed.
- The error messages appear in the list file and on the screen. If
- the list file is the screen itself then the error message appears
- only once. The messages appear in the list file following the list
- of the line where the errors were detected. The assembler writes
- out the type of the error and the message. This message is some
- short remainder in case of WARNING, NORMAL, and FATAL messages. In
- case of INTERNAL message the text is only a three digit number. In
- case of MESSAGE type the text is determined by the assembly file.
- The next chapter contains the messages that are generated by the
- assembler itself. The messages are sorted into alphabetical order.
- The list of the error messages
- ------------------------------
- The items of the list contain the error messages and some
- explanation and advises how to recover if such an error appear.
- The first character of the line means the type of the messages. W
- for WARNING,N for NORMAL, F for FATAL. An item contains more
- messages if the same explanation describes them.
- N #ifdef needs an identifier
- N #ifndef needs an identifier
- The directives #ifdef and #ifndef need an identifier in the same
- line. These directives switch the compilation on and off if the
- identifier was declared or if was not.
- N #stack needs variable
- The directive #stack needs a variable in the same line. Get sure
- that you wrote the identifier of a variable and not a label in the
- line of the directive.
- N #until for an outer #repeat
- PCMAC found some #until directive for which it can not find the
- directive #repeat. The directive pairs #repeat,#until and
- #while,#wend can be nested but not overlapped. Remember that these
- directives can be used only in macro definitions.
- N #until without #repeat
- PCMAC found some #until directive for which it can not find the
- directive #repeat. You forgot to write the #repeat for the pointed
- #until or you used two different #until directives for the same
- #repeat. Remember that these directives can be used only in macro
- definitions.
- N #wend for an outer #while
- PCMAC found some #wend directive for which the directive #while
- was not declared before an unclosed #repeat. The directive pairs
- #repeat,#until and #while,#wend can be nested but not overlapped.
- Remember that these directives can be used only in macro
- definitions.
- N #wend without #while
- PCMAC found a directive #wend for which it can not find the
- directive #while. You forgot to write the directive #while or you
- used two #wend directives for the same #while. Remember that these
- directives can be used only in macro definitions.
- N #while has no #wend in the macro
- PCMAC reached the end of a macro definition and found a #while
- for which there was no closing #wend. Remember that all the #while
- directives have to have their pairs. The same holds for #repeats.
- Remember that these directives can be used only in macro
- definitions.
- N ( missing in the macro definition
- Starting a macro definition PCMAC found the keyword macro but
- the character ( is missing after it.
- N ( expected!
- PCMAC found an expression in which a function name is not
- followed by a left brace. Remember that the characters ( and [ can
- be used in expression to close subexpressions, but argument of
- predefined functions can only closed between ( and ).
- N ) missing after the const definition.
- PCMAC found the end of the line following a const definition but
- the definition was not close with the character ).
- N , missing between the expressions
- In expression lists you have to separate the expressions with
- commas. You separated the expressions with some spaces or you
- made some syntactical mistake in the first expression and PCMAC
- thinks that the separating comma is missing.
- N := expected
- You forgot to use the sign := in a const definition. You
- probably wrote spaces or a single = sign.
- N ASCII code out of range
- The value of an expression following the directive #char is not
- between the interval 0..255. Try to calculate the value of the
- expression by hand and get sure that the value is really valid.
- W ASCII number is too long
- An ASCII number starts and ends with an apostrof (') and can
- contain at most four characters between. You wrote more than four
- characters or only forgot to type the closing apostrof.
- N Assign for a non variable symbol
- The assignment can be used only to assign value to a variable.
- The Identifier that stands in the line was declared as label. Use
- some other identifier.
- F Bad macro library file
- PCMAC tried to include a file as a macro library file, but the
- file, of which the name was given following the directive #lib, is
- not a macro library file. The file might damaged. In this case you
- have to recompile it with PCMAC using the command line option -K.
- Be sure that you named the compiled file following the directive
- #lib and not the original macro definition file. If you mixed up
- the two files than you have to change the file name after the
- directive #lib or you can use the directive #macros.
- W Character not terminated
- You forget to write out the terminating apostrof of a character
- constant before the end of the line. Terminate the character
- constants with the character (')!
- N Code generating error !
- PCMAC tried to generate a byte for an address that is lower than
- the lowest address of the first pass or higher then the highest
- byte of the first pass. It means that the different passes
- generate different code. It is hard to recover of this error. It
- is usually caused by conditional compilation that depends on the
- variable pass. Get sure that the blocks that are not compiled in
- one of the passes do not generate code.
- N Dangling #endif
- A line containing a directive #endif encountered and PCMAC can
- not find the directive #if, #ifdef or #ifndef. You forgot to write
- the line that contains that directive or used two different #endif
- directives for the same #if??? directive.
- N Empty syntax definition
- You specified an empty string as syntax definition of a macro.
- This macro definition can not be matched by any line, so such a
- macro definition is out of use. Do not do it.
- F End of memory!
- Well, this error is a very unconfortable one. You get an error
- message though you made no mistakes. Only the memory of your
- computer is to small. Buy some more memory if possible. A cheaper
- solution is to split up the assembly program into more files and
- compile it with the option -o and link the object files. Use less
- variables, labels and macros.
- N Error in the file name
- A directive #include, #macros or #lib is followed by a file name
- that is closed between " or <> pairs. You should not mix up the
- different terminators. If you start a file name with < then you
- have to terminate it with > and if you opened a file name with "
- then you have to close it with ".
- N Expression must be predefined
- The expression standing on the right hand side of an command :=
- or equ is not evaluateable. This is because some label is not
- defined yet. An expression like that has to be evaluatable.
- N External can not be public
- You declared a label as public and as external. It is no use and
- impossible.
- N External in an expression
- A variable that is declared as external can not be used in an
- expression. Use two macro definitions with the same syntax string
- for the same instruction if you want to refer expressions and
- external labels as macro arguments.
- N External with no -o option
- N Public with no -o option
- You tried to compile a program that contains external labels.
- This is a mistake. You probably forgot to use the option -o. If
- you really want to generate a tsk file immediately then use the -t
- option, but be sure that all the external labels get value.
- N Identifier expected after public
- There must be one or more identifiers following the keyword
- public. The identifiers must be separated by commas.
- N Identifier expected in the CONST!
- You forgot to specify an identifier for the symbolic constant.
- Without this name you can not reference the constans so no use to
- declare literals without name. Insert a name between the sign :=
- and the keyword 'const'.
- N Identifier missing as a const definition
- This message appears if the assembler does not find the next
- literal following a comma. You probably deleted the last literal
- of the list but forgot to delete the separating comma or you just
- simply mistyped something.
- W Inconsistent options -o -h
- F Inconsistent options -o -K
- W Inconsistent options -o -t
- The options -h, -K and -t can or may not be used with the option
- -o. Read through the chapter that tells you what are caused by the
- options.
- W Input file name *.o
- The extension of the input file name is the letter o that is the
- default extension of the generated file if the -o option is
- present. Do not use the .o extension for source files. If you
- compile a file with the extension .o to object file and you
- do not specify output file name then the assembler will put the
- object code into a file that is named with the same name as the
- input but the extension will be .q for MSDOS or .O for UNIX.
- (This is because MSDOS treats .o and .O the same.)
- N Invalid case suboption
- The option -c has no suboption so it has to be followed by a
- space. You should not specify UNIX style options. E.g.: You should
- write -c -K instead of -cK.
- N Invalid list suboption.
- The option -l can be followed by the character n. This letter
- tells PCMAC that the name of the list file follows. You can not
- specify any other sub option.
- N Invalid option
- You specified an option letter that is not used by PCMAC. You
- probably wrote -k instead of -K.
- N Invalid const number
- You used a number following the macro argument character for
- which there is no argument for. Do not forget that the numbering
- of the arguments start with zero instead of 1.
- N Macro definition nesting is not allowed
- N Macro definition not terminated
- Macros can not be nested. This speeds up the assembler and
- prevents the user to generate memory vasting constructions. All
- neccessary definitions can be made without nesting. If you do not
- know what we are talking about because you did not want to nest
- any macro into another then you probably forgot to write the line
- endm. It can be the case even if you got the first error message
- because PCMAC does not know whether you forgot to close a macro
- or wanted them to be nested.
- F No more stacks
- At most 100 stack can be opened at a time. It must be enough for
- every development. You tried to open the 101. stack. It can happen
- if open a stack inside of a macro in a loop or if the macro is
- recursive.
- N No label whom assign the value to
- N No variable whom assign the value to
- The mnemonic equ or the sign := is not preceeded by identifier.
- These instructions are to assign value to a label or to a
- variable.
- N Non ascii character for macro number
- N Non ascii character for macro prefix
- The value of the expression following the directive #macarg or
- #macnum is not between the interval 0..255. Try to calculate the
- value of the expression by hand and get sure that the value is
- really valid.
- W Non octal character in string number
- This is a very dangerous warning. This is generated if a \
- character in a string is followed by the character 8 or 9. This is
- dangerous because you can think that the assembler generates bytes
- with the value 8 or 9. However the assembler generates bytes that
- hold the ASCII code of the characters '8' or '9'. This warning
- message will not appear if the ASCII radix is set to decimal with
- the directive #decimal. In that case the assembler will generate a
- byte whith he value 8 or 9.
- W Non relocatable for byte offset
- W Non relocatable for word offset
- W Non relocatable for dword offset
- The expression following the drb, drw or drd command is not
- relocatable. This is probably wrong.
- N Not 16 bit value for a word
- The value of the expression following the directive dw is not a
- 16 bit value. The assembler does not truncate the values
- automatic. You have to declare the truncation and write:
- '(expression)&0FFFFh' instead of 'expression'.
- N Not closed loop in the macro
- PCMAC reached the end of a macro definition and found some
- unclosed loop. It can either be #repeat,#until or #while,#wend
- loop. Read the macro definition and correct it.
- F Not only macros for macro library
- You tried to compile a file with the option -K that contained
- code generating instructions. These instructions can not be put
- into a macro library file. Eliminate these lines or do not compile
- this file but include it with the directive #macros.
- N Not used user stack free
- You specified a stack in the directive #clostack which was not
- opened with the directive #stack. You tried to close the stack
- twice or you close the stack in a macro that is recursive or
- contains loop.
- W Octal number terminated by digit
- This is a dangerous warning and never skip it! You used an
- escape sequence in a string and the octal numbers were terminated
- by a non octal digit that is 8 or 9. You can easy read it as a
- digit that belongs to the octal number and interpret it as a
- decimal number. Be sure that you really want a nonprintable
- character followed by the character 8 or 9. This message will not
- appear if the radix of the ascii numbers is set to decimal with
- the directive #decimal.
- N Poping an empty stack
- N Reading the TOS of an empty stack
- The assembly program wants to fetch a value from a compile time
- stack that is empty. In the current version of the assembler there
- is no way to check if a stack is empty.
- N Public symbol was not defined
- You declared a variable as public but it got no value during the
- passes.
- N External with no -o option
- N Public with no -o option
- You tried to compile a program that contains external labels.
- This is a mistake. You probably forgot to use the option -o. If
- you really want to generate a tsk file immediately then use the -t
- option, but be sure that all the external labels get value.
- N Redefining a label
- N Redefining a symbol
- N Redefining an identifier
- A label may appear only once on the left hand side of a line. A
- literal can stand in different definitions, but the const names
- has to be different. An identifier can be used to identify a
- label, a variable, const name, but only one at a time.
- Many programmers cause the first error message forgetting that
- the l;abels inside of a macro are not local. They will appear as
- labels so many times as many times the macro is extended. To
- generate local labels you have to use the macro numbering
- characters with which you can extend your labels with numbers.
- W Relocatable data for byte
- The assembler does not relocate byte values. If a byte value is
- relocatable then a mistake is very probable.
- N Relocatable value for ASCII code
- W Relocatable value for list switching
- N Relocatable value for macro number
- N Relocatable value for macro prefix
- N Relocatable value for stack number
- The value of an expression is relocatable, but the way of usage
- is not. If you really want to use relocatable values at these
- places then use the doureloc function.
- N Right bracket missing in the expression
- You can use () and [] characters to close subexpressions inside
- of an expression. The subexpressions can be nested any level deep,
- but all '('s have to have the pair ')' and the same is true for
- the '['s. You can not close a subexpression opened with '(' with a
- ']' and vice versa. It is a good style to use one of the brackets
- to close subexpressions. Some assembly languages use the ()
- brackets to refer to memory and other use the [] brackets. You do
- use the other one to close subexpressions. Do not forget that the
- arguments of the predefined functions should be closed with ().
- N Const definition can not be inside of a macro
- A const definition can only be global in an assembly program and
- can not be localised for a macro. That is the reason for which you
- can not define a const definition inside of a macro. If you get
- this error message, but you did not wan to declare const inside of
- a macro then you probably forgot to close the previous macro. It
- is a good style to collect all the const macro definitions to the
- start of the file before the macro definitions.
- N Syntax error in the expression
- The assembler found an expression that it can not understand.
- N String not terminated
- The closing " is missing at the end of the string. Unlike in C
- language you can not continue a string in the next line using a \
- to close the line.
- F Too deep include in the file system
- An included file may include another one but the nesting must
- not exceed the number 5. This deepness is enough for the most of
- the applications. Deeper include appears if you probably made
- a loop and the files recursively include each other.
- N Too few const definition
- The syntax definition string contains more asterisks than the
- number of the consts on the end of the syntax definition line of
- the macro. In this case the assembler does not know what kind of
- arguments should be excepted. If you wanted to have an asterisks
- in the line then do not forget to preceede it with a backslash in
- the syntax definition string.
- F Unable to open the library file
- F Unable to open the object file
- F Unable to open the output file
- N Unable to open the list file
- The assembler can not open one of the files. It can happen if
- you specified a wrong directory or mistyped the name of the file.
- It also can happen that the assembler wants to open the output
- file but it already exists and protected. In this case the
- assembler can not delete the old file to open the new one with the
- same name. The assembler was developed to be a very safe tool and
- it will not damage your file system.
- N Unbalanced #ifs
- The assembler found a directive #if for which there is not
- #endif. Get sure that you closed all the #ifs. The directive pairs
- #if\#endif, #ifdef\#endif and #ifndef\#endif can be nested any
- level deep but each has to have its pair.
- N Undefined label in the expression
- One of the labels in the expression is not defined. It also can
- happen that you try to compile a file with the option -t and
- forgot to include some of the files that define the value of the
- variables.
- N Unexpected characters on the end of the line
- The assembler found some characters on the end of the line with
- which it can not do anything. You probably forgot to preceede the
- comment with a ; character or mistyped something.
- N Unknown byte order in the #dw directive
- N Unknown word order in the #dd directive
- The directives #dw and #dd should be followed with the character
- pairs lh or hl. Nothing else can stand on that place.
- N Unmatchable syntax definition
- The assembler generates this error message if it found a syntax
- definition string that is not matchable. The assembler does not
- discover the unmatchability of the syntax string so: if you get
- this error message then there is no line accepted by this syntax
- definition, if you did not get this message then there is no
- guarantee that there is line.
- N Variable can not be public
- An identifier that was declared as public is used as variable.
- Only labels can be public. Variables are tools to be used while
- compile time and not while link time.
- W Variable was not explicitly declared
- A variable has to be declared in the instruction 'var'. If an
- identifier was not declared as variable and stands on the left
- hand side of a assignment then the assembler automaticly declares
- the it as a variable but sends the warning message.
- N Wrong binary number
- N Wrong octal number
- N Wrong decimal number
- N Wrong hexadecimal number
- The assembler found a mistyped number. You can get the third
- error message for hexadecimal numbers if the number ends with the
- hexadecimal digit 'D' or 'd' and you forgot to use the 'h'
- postfix. This is because in this case the assembler thinks that
- you used the optional decimal postfix 'd'.
- N Wrong stack number
- The assembler generates this error message if the program refers
- to a stack that was not opened or is closed yet.
- N " missing after the macro definition
- The assembler generates this error message if the macro
- definition string is not terminated with a ".
- N " missing in the macro definition
- A macro syntax definition is closed between ( and ). The first
- member of the definition is the syntax string that starts with a
- character ". The assembler can not find this character.
- N " missing after the message in an 'message' directive
- N " missing after the message in an 'warning' directive
- N " missing after the message in an 'error' directive
- N " missing after the message in an 'fatal' directive
- The assembler generates this error message if the message
- string following the directive is not terminated before the end of
- the line.
- N " missing after the 'message' directive
- N " missing after the 'warning' directive
- N " missing after the 'error' directive
- N " missing after the 'fatal' directive
- The directives #message, #warning, #error and #fatal has to be
- followed with a string.