Scenergy #01
31 мая 1999

Coding - On the use of macros or TASM 4.12 - RULEZ!

<b>Coding</b> - On the use of macros or TASM 4.12 - RULEZ!
          On the use of macros or

           TASM v4.12 - rulez!



              0. Entry

 A little strange title for an article, not
find? :) But the content is
corresponds to the name.
 Write this article prompted me
conversations FIDO'shnoy echo ZX.SPECTRUM, from
I've learned one in particular
amazing thing for me - it turns out
most people simply do not know what
such macros and conditional compilation and
What do they eat it all. Another driving
power to writing this article was
burning desire to once again say: "What
happiness that the world has such a
wonderful assembly as TASM v4.12 by
RST7/CBS! ". Well, he said, is now available
sleep peacefully. :) In other words part
This article aims to show what
Still TASM 4 highlights from the rest
assemblers that it is such a thing
No, unfortunately, nowhere else, and because
Why I chose it after
tried about a dozen assemblers.
 But it is distinguished by its two above-mentioned
things - the presence of macros and conditional
compilation. More precisely, there is another thing -
keyboard macros, but the theme of this
Article does not apply, although too
is nemeryannom rulez'om:)
 I will immediately say: this article - no agitation
All encoders "go to the TASM!" (Well
can only to some extent), and
rather a call to the authors assemblers -
why such wonderful things so far
not all assemblers?
 But back to the main topic.

 First, for those who do not familiar with
notions of "macro" and "conditional
compilation, "I will try to outline
explain what it is.


          1. What are macros?

 Thus, the macro is called design
following form:


         DEFMAC <Macro name>

         <The body of a macro>

         ENDMAC

 At the same time <Macro name> - any label, and
macro body - any piece of code in
standard syntax of the assembler.


 Example macro:

        DEFMAC CLRSCR

        LD HL, # 4000

        LD DE, # 4001

        LD BC, # 17FF

        LD (HL), L

        LDIR

        ENDMAC

 Using macros in the code
carried out by specifying in the body
program a macro name:


        HALT

        XOR A

        OUT (# FE), A

        CLRSCR; Use a Macro


 When you compile will be generated
the following code:


        HALT

        XOR A

        OUT (# FE), A

        LD HL, # 4000 This piece of

        LD DE, # 4001, package insert

        LD BC, # 17FF; instead of macro name.

        LD (HL), L;

        LDIR;

 Macros can have parameters. In
Syntax TASM'a parameters are referred to as
\ 0 \ 1 \ 2, ... \ 9. Ie each macro
You can submit up to 10 parameters.
We'll see how it is used as an example
the same treatment. But now it will be
is not only clean the screen, and any
chunk:

        DEFMAC CLEAR

        LD HL, \ 0

        LD DE, \ 1

        LD BC, \ 2

        LD (HL), 0

        LDIR

        ENDMAC

 Accordingly, a call to the macro:


        HALT

        XOR A

        OUT (# FE), A

        CLEAR # 4000, # 4001, # 17FF

 The generated code is naturally identical.
 But this does not look very nice.
Therefore it is better to alter this slightly
Macro:


        DEFMAC CLEAR

        LD HL, \ 0

        LD DE, 0 + ((\ 0) +1)

        LD BC, 0 + ((\ 1) -1)

        LD (HL), 0

        LDIR

        ENDMAC

 Accordingly, change and challenge:

        CLEAR # 4000, # 1800

 I hope you understand? The only question
may be on terms for DE and BC.
Let me explain: the parameters passed to the macro,
in brackets in order to be
was passed as a parameter is not
only constants, but also an expression. A "0 +" in
beginning is necessary in order to show
assembler that this is not a team LD DE, (nn),
and LD DE, nn.
 Naturally described by macro primitive
but it is clear and gives an idea of
that such macros.


    2. What is conditional compilation?

 Now the conditional compilation. In
Syntax TASM'a conditional compilation
as follows:

. IF <expression>
<1 st piece of code>
. ELSE
<2 second piece of code>
. ENDIF

 <expression> - Any expression understood
assembler.
 So, if the value of <expression> on
compilation stage will be equal to 0, will
compiled "1 st piece of code> if the same
No, it will be compiled <2-d piece
code>.
 Why do it? This is most often
used to have
ability to generate different code from
the same source code without
changes. A typical example - you have
a project that you develop.
While the project is in development
and debugging, there are usually pieces
debugging code (different trap
plugs, press SPACE to check
output, some counters and interrupts
etc.). Of course, that this whole
debug code will have to clean up the stage
assembling the finished project. Typically, this
results in a crawl on the source from
muttering to himself, "Well, because somewhere
here was this test ... Where she
had gone ... ?:) And then, when suddenly
again be required to return the debug code
in place (which also happens often, because
finished project respectable size rarely
going from the first time), all of this
procedure is repeated again, and then another
and again ... One word - sad
sight ...
 Now consider the same situation but with
using conditional compilation:
 1) At the beginning of the source code is written the line:
DEBUG EQU 0 0 - condition
 2) The whole debug code written as:
. IF DEBUG

. ENDIF

 Now, in order to compile
debug version of the program we need
set DEBUG = 0, and to compile
version without debugging code - set
DEBUG = 1. That's it!
 I think you will agree with my opinion,
that work so much easier.


         3. Examples of use

 Consider some other possibilities
use of macros and conditional compilation
in your programs. Because teacher out of me
worthless, and examples on the go, I come up with
I can not - I will take only the real
examples of the use of my programs.


         3.1 Memory Allocation

 Perhaps it is the use of macros found
most widespread in my
programs. Simply put, all my
programs written in the last year
to work with in this way
memory allocation. And I find it
very convenient.
 Here I will briefly describe the methodology and give
Examples of macros, and the sources with this
module can be found in the annex.
 The main idea is to
facilitate the programmer task allocation
dynamic memory and automate
control over its overflow.
 I think any programmer faced with
such situations, when his buggy
program due to the fact that he was singled out by
table or generated by the procedure for 1
bytes less memory than necessary. Also
probably all experienced
the need to manually recalculate the addresses of
location in the memory of a dozen plates,
If the first of them suddenly changed size.
 So, the use of macros allows
completely relieve the programmer from all
these problems!
 First you need to reach agreement on
the organization of memory. I will describe how
it's done for me, but actually this method
You can fit under any scheme
memory allocation.
 Thus, memory conventionally divided into
following areas:
# 6000 - # 7FFF - Slow memory.

              Used to store

              tables.
# 8000 - # xxxx - A program code.
# Xxxx-# BDFF - Fast memory. Used

              to store the generated

              procedures, as well as those

              tables, which are not penetrated into the

              slow memory.
# BE00-# BFFF - Table of interruptions and all that

              associated with a handler

              interrupts.
# C000-# FFFF - Upper memory. Used

              for the storage of large tables

              and / or procedures.
 Using a memory allocation, we
additionally provide greater
probability of normal operation of programs
machines with slower memory. Well, okay,
is irrelevant.
 As a rule, you want to type 2 released
Memory - with an arbitrary address and
address aligned to the boundary of 256 bytes
(Ie the address mask # XX00). So
way to solve the problem of allocating
memory, we need six macros (3 types
Memory * type 2 selection):

 To allocate memory with arbitrary
Address:
GET_SLOW_MEMORY - in slow memory
GET_FAST_MEMORY - in fast memory
GET_UPPER_MEMORY - in upper memory

 To isolate the memory address,
aligned along the boundary of 256 bytes:
GET_SLOW_MEM_XX00 - in slow memory
GET_FAST_MEM_XX00 - in fast memory
GET_UPPER_MEM_XX00 - in upper memory

 The general format of the call:
GET_nnn_MEMORY Variable, Mem_Size
GET_nnn_MEM_XX00 Variable, Mem_Size

 Example:
GET_SLOW_MEMORY PROC_1, $ 120
GET_SLOW_MEMORY PROC_2, $ A0
GET_SLOW_MEM_XX00 TABLE_1, $ 200
GET_SLOW_MEM_XX00 TABLE_2, $ 100


 As a result, when we compile:
PROC_1 = # 6000
PROC_2 = # 6120
TABLE_1 = # 6200; And no # 61C0!
TABLE_2 = # 6400
 Accordingly, if the size of any
allocated memory area will change - all
addresses will be converted at compile
automatically, while preserving all
necessary alignment of boundaries 256
B!

 Well, not a fairy tale right? :)

 We'll see how it is implemented:
; SLOW_MEMORY - a variable that
; Stores a pointer to the first free
; Bytes.
; Originally SLOW_MEMORY = # 6000.

; Macro Settings:
; \ 0 - The name of the variable created
, \ 1 - Size of memory allocation
DEFMAC GET_SLOW_MEMORY
; Create a variable
\ 0 EQU 0
; Assign it to the current value of the index
; Free memory
\ 0 = SLOW_MEMORY
; We correct pointer value in
, According to the size of allocated block
; Memory.
SLOW_MEMORY = SLOW_MEMORY + (\ 1)
ENDMAC

DEFMAC GET_SLOW_MEM_XX00
; Create a variable
\ 0 EQU 0
; If the low byte of current address
; Pointer is not zero ...
. IF SLOW_MEMORY '# FF-0
. ELSE
; ... That reposition the pointer to the next
; Memory address aligned to the boundary
And 256 bytes.
SLOW_MEMORY = ((SLOW_MEMORY / # 100) +1) * # 100
. ENDIF
; Assign a variable current value
; Index of free memory.
\ 0 = SLOW_MEMORY
, We correct value of the pointer in
, According to the size of allocated block
; Memory.
SLOW_MEMORY = SLOW_MEMORY + (\ 1)
ENDMAC

 Macros for fast and upper memory work
similarly.
 In addition, the file MEMORY.A, located
in the application, you can see the macro
DISPLAY_INFO, which helps track
overflow the allocated memory. Because of its
Large I not give it here
I will.


              3.2 Calculations

 Macros are great easy task
computation of an expression in your
program.
 It is often necessary to ask
any address in the form of tags in order
to continue to use it. If
like to address 1 - it can be defined
manually. But if, for example, ten,
moreover they have from time to time
change - unwillingly think. Especially
often happens with screen addresses. For
This, too, can write enough
simple macros, which, nevertheless,
life much easier:

Calculation of the display address.
; Macro Options:
; \ 0 - The name of the variable created
, \ 1 - X coordinate (in the familiarity)
, \ 2 - Y coordinate (in pixels)
DEFMAC GET_SCRADR
\ 0 EQU # 4000
\ 0 = \ 0 + ((\ 2) '# C0 * 32) + ((/ 2) '7 * # 100) + ((\ 2)' # 
38 * 4) + ((\ 1) '# 1F ) ENDMAC


Calculation of addresses in the attributes.
; Macro Options:
; \ 0 - The name of the variable created
, \ 1 - X coordinate (in the familiarity)
, \ 2 - Y coordinate (in the familiarity)
DEFMAC GET_ATTRADR
\ 0 EQU # 5800
\ 0 = \ 0 + ((\ 2) * 32) + ((\ 1) '# 1F)
ENDMAC

 In addition, if you want the macros
elementary altered the fact that
immediately write to the address of the memory - it
very convenient for the preparation of various
Tables of addresses. For example:

DEFMAC DEFW_ATTRADR
DEFW # 5800 + ((\ 2) * 32) + ((\ 1) '# 1F)
ENDMAC

ADR_TABLE

        DEFW_ATTRADR 10,5

        DEFW_ATTRADR 12,6

        DEFW_ATTRADR 14,7

        DEFW_ATTRADR 16,8

        DEFW_ATTRADR 18,9


 This, of course, just examples. Real to
macros can be implemented much more
complicated things. For example, in Scenergy main
menu on my macros written calculation
table of pointers to sprites,
components of the animation menu items. When
This set only the number of sprites and
their size, and macros recalculate
addresses, and even with the transition to
next page (as a sprite
assigned to 2 pages). But here I am this
Macro will not lead because of its size
(2 screen TASM'e:)).


           3.3 Data Structures

 With the help of macros can be easily realized
work with data structures.
 Surely each of you for writing
program had to deal with the fact
that data on some objects have
several fields, these fields of different
type.
 For example, data on the menu:
[Byte] - X coordinate
[Byte] - Y coordinate
[Word] - Pointer to next paragraph
[Word] - Pointer to the previous item
[Byte] - Length
[Byte] - Hotkey
[Byte] - Type menu item
[Byte] - Additional flags
[Word] - Pointer to a procedure handler
[Word] - Pointer to the parameter
[Word] - Pointer to the commentary
[Data] - The name of the menu item
 Incidentally, this data structure is actually
describes a menu item in Scenergy Setup'e.


 Each element of the data structure
characterized by 2 things:
 - Its type
 - Offset of the structure

 As a rule, these programs shift
are given constants. Accordingly,
If, God forbid, some sort of box should be
remove or change its type (a
hence the size) - all the bias and
change! And therefore, you will be
at best, re-counted all
bias and stuff them into the appropriate
EQUS. Or, if you write all ugorazdilo
these shifts within the program as a
numbers - You will spend a long
time searching for all these shifts, but
More then check out - and whether he had forgotten something?
In one word - fun on the verge
masochism:)
 What is here can help macros? But
nothing. Write a little macro:
___ORG EQU 0

        DEFMAC _SZ
\ 0 EQU ___ORG
___ORG = ___ORG + (\ 1)

        ENDMAC

 And ask all the bias in the following form:
___ORG = 0
_SZ _MI.X, A
_SZ _MI.Y, A
_SZ _MI.NEXT, 2
_SZ _MI.PREV, 2
_SZ _MI.LEN, A
_SZ _MI.HOTKEY, A
_SZ _MI.TYPE, A
_SZ _MI.FLAGS, A
_SZ _MI.HANDLER, 2
_SZ _MI.PARAM, 2
_SZ _MI.COMMENT, 2
_SZ _MI.TITLE, 0

 What we do for you?
1) There is no need to manually
assume that all the bias, there is no
the probability of making a mistake in this case.
2) It turns out more clearly.
3) Any change in all recounts
displacements will be made automatically!

 And another thing. Namely, how to set these
data structures. Usually it looks
something like this (for the structure of the menu item):

MI_1; Previous menu
MI_2

        DEFB 3,5

        DEFW MI_3, MI_1

        DEFB 10
. ENDIF

. IF USE_SMULT8

        
. ENDIF

. IF USE_MULT16

        
. ENDIF

. IF USE_DIV8

        
. ENDIF

. IF USE_DIV16

        
. ENDIF

 All this is recorded as a separate
module, for example MATH.A. Now if

        DEFB "I", 2,5

        DEFW HANDLER, PARAM, 0

        DEFB "MENU ITEM", 0
MI_3; next menu item

 Using the same macro it can
as follows:

        MI.X = 0

        MI.Y = 1

        MI.LEN = 12

        MI.TYPE = MIT_NORMAL

        MI.FLAGS = MIF_ACTIVE + MIF_SELECTED

        MI.HANDLER = CONTROLS
        MI.PARAM = 0

        MI.COMMENT = C011

        MENUITEMDATA "~ CONTROLS ..."

 This is a real piece of source code from Scenergy
Setup'a. In addition, the use of
macros allowed in this case
get rid of the tedious operations
combining menu items in a doubly-linked
list. But here I am, these macros also
not cite due to their bulkiness.
 I personally this way of defining data
like more, though, as it turned out, my
view is shared by no means all. For example,
universally respected Oldman criticized this
way to the nines:) Of course, this case
taste, but people have a right to know about
alternatives to the standard work on
structures.


        3.4 Enhanced Syntax

 In principle, work with data structures
implemented on a macro is also
extension of the syntax, but I made it to the
separate part. Here we talk about
extending the syntax of the assembler.
Of course, best of all it can tell
author TASM'a - RST7. One can think of
to his library 6502.A, which is not
simply extends the syntax of the language, and, in
essentially turns the TASM to compiler
an entirely different processor!
 But to such heights, we do not rise
shall we start with something more
simple. Incidentally, I deliberately did not touch
such a possibility as macros in TASM'e
parse the string parameters as this thing is not
so trivial to explain
whatever it is. Those to whom it will be
be - yourself and read the description TASM'a
understand.
 So, what about the syntax. To start
see how we can implement
STROM'ovskie macros, such as LD
HL, DE:

        DEFMAC LD_HL_DE

        LD H, D

        LD L, E

        ENDMAC
 Work with multiple parameters in LD
can also be done with macros, but
this is not a trivial task. Who is
will have to - do it yourself.
 So with the help of macros can be done
more readable some areas
Your code. I have already cited the example of
cleaning, these things can come up with
set.
 In addition, using conditional compilation
You can make back the beginnings of optimization.
For example:

        DEFMAC LD_A

        . IF \ 0

        XOR A

        . ELSE

        LD A, 0 + (\ 0)

        . ENDIF

        ENDMAC
 I hope you understand? If the option is a macro
zero - instead of LD A, n is XOR A.
This is necessary if A is not assigned
constant, and the expression, or mark and advance
know what will be its value. This
only a simple example that you have caught
the basic idea.


  4. Increase the flexibility of code using

           conditional compilation.

 What I mean by the words,
in the headline? A very simple
thing - the minimization of patches ready
sources to give them a kind of
adapted for use in
other programs.
 Consider an example. Let's say
You have a piece of code that is almost
unchanged passes from one of your
program to another. This may be different
things. For example, I have this group of modules
providing a variety of low-level
function to create effects in chunk'ah.
 What usually makes a programmer, if he
want to use a piece of his
source code in another of his program? Usually
first he knows his previous
source code, trying to understand what other
procedures and tables are needed
piece of code that he wants to move,
What is the subtlety in its use.
We must also control - not
I copied something extra?
 Using conditional compilation
avoids all these problems and
make your source code portable between
all of your programs.
 Consider a typical example - the procedure
ralizuyuschie math. As
Typically, each encoder has a set of
similar functions for all occasions -
multiplication, division, etc. And often
These functions are not coder wrote himself, and takes
ready. Ie to repeat them "out of my head," he
unlikely to be able to. So, for example,
he needed a procedure for multiplication. That
is he doing? Usually begins
remember: as to what program I
used this procedure last?
Then start searching for the source of this
program. Then - in search of this procedure
source code. And so every time.
 You can certainly go the other way -
keep all such procedures as
separate source code and take pieces of code from
him. Can be stored on a separate disk
many small ishodnichkov. And you can go
in another way:
 All these procedures are combined into
one module. But not just so, and with
additional rail:
 - First is the definition of a set
conditions:

USE_MULT8 EQU 1; Multiplying D * E = HL, unsigned
USE_SMULT8 EQU 1; Multiplying D * E = HL, signed
USE_MULT16 EQU 1; Multiplication HL * DE = HLDE, unsigned
USE_DIV8 EQU 1; division of H / L = HL, unsigned
USE_DIV16 EQU 1; division of HL / DE = HL.DE, unsigned

 In the future, using them, we can
We provide the necessary procedures.

 - Then comes the description of the procedures themselves:

. IF USE_MULT8

        
any program you need any
procedure of multiplication / division of one of those that
is in a module, you will need to
only do 2 things:
 - Add to the source line:
USE_ 




Other articles:

Chars - the charts with 116 questionnaires staff meeting Scenergy.

Charts - the best: Organizer, Musician, Coder, Cracking group, Scener, Group, Demo, Mazazine, Party.

Charts - Best: Single Coder, Cracker, Graphilian, Organizer, Musician, Group, Site.

Charts - Statistics - the numbers and thinking.

Coding - Driver RAM DISK'a for ZX-Spectrum'128.

Coding - On the use of macros or TASM 4.12 - RULEZ!

Coding - the implementation of Phong Bump Mapping on the Speccy.

Coding - sync with the music in demah.

Cracking Scene - crack contest.

Cracking Scene - Illegal scene on the Speccy.

Demo Parrt - venue CC'999.

Demo Party - gloomy thoughts Random'a: "What should I do for you to believe in design Haosa'999?"

Demo Party - New demopati: Designs Haosa'999 - past and future.

Demo Party - Pro Fun Top and all-all-all ... (Belated report Serzh'a in 5 parts)

Demoscene - Chaosite - technical data on Haosaytu.

Demoscene - the history of composition and softografiya Omega Hackers Group.

Demoscene - A new group Novgorodoskaya "RaZZLeRS".

Demoscene - An Open Letter to the scene and Kano himself.

Demoscene - the composition and the contacts of the Lithuanian group zERo.

Editorial - Information section - INDEX ...

Groups - statistics about the active groups: Digital Reality

News - Codebuster track stolen from Zhenya? Fatality site has moved. Extreme leaves the Spectrum. Wait for a 4-th number Subliminal Extacy? Lithuanian group Zer0 longer suschesvuet. Phantasy returned to the stage! Problems with Complex compo. Disputes about associations.

Sceneexplorer - Conments - based on questionnaires: "What about the Sprinter and dumate GMX", "where taking the program," in which networks have addresses.

Sceneexplorer - The results of the survey.

Sceneexplorer - List of questioning.

Scenergy - How to contact us.

Scenergy - Work with Scenrgy Setup.

VIP - Interview with David Brabenom c, author of the great game Elite.

VIP - An Interview with galandskoy demo group The Lords.

VIP - An interview with the Moscow Spectrum team - Cosmic (Progress).

Warez Pack - description of the application log: Energy Trackmo, Forever: Final Release, Yes.

Warez Pack - description of the application log: First Association

Warez Pack - description of the application log: Pussy: Love from Titanic, CrossWord.

Warez Pack - description of the application log: SpriteLand v1.27

Warez Pack - description of the application log: Worms


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Similar articles:
Advertising - Ads are published free of charge (at least until slyuchae).
B.B.S. News - open new servers LOST BIT & R'S BBS.

В этот день...   21 November