|
Inferno #06
03 декабря 2004 |
|
For Coderz - Macros Part 2 - makes your life in programming.

On a macro poor Say a Word-2
or
The macro returns.
In this article we continue our acquaintance with
representatives of a remarkable family
Macro:) You'll learn how to use them to
further simplify your life with programmirovanii.Kak always
examples provided with respect to ALASM. For ALASM version 4.46
and above macro parameters identified by the prefix''instead of
the colon.
You probably already know how to get addresses, justified by
some sort of edge chains. Here is one of the following:
ORG '($ -1) +1 <8
This alignment of the boundary of 256 bytes.
You can define a more general case:
MACRO ALIGN
ORG
+ $ -1 '(- (
))
ENDM
[It is desirable to use instead of ORG DS,
to prevent the memory is not known what, what is the unknown
that is packed usually worse than zero. Make a macro with DS
- This is your homework.]
- This option is a macro. In this
If the value is the boundary alignment. [In parenthesis it is
concluded because that the parameter can be an expression.
When you call the macro parameters are passed to
as they stand in line vyzova.Esli macro calls the macro, the
parameters external macro disclosed.] Obviously,
that if the program many of these alignments, then there are
quite a large loss of memory. But we have macros, so we can try
to control these loss and then try to minimize the vat. Modify
our macro:
MACRO ALIGN
LOCAL
OLDADR = $
ORG
+ $ -1 '(- (
))
IFN $-OLDADR
DISPLAY "Memory leak before", / H, $
DISPLAY "Leak size =",$- OLDADR
ENDIF
ENDL
ENDM
Now, when compiling we get
messages such as:
Memory leak before # a700
Leak size = 253
If we soptimiziruem code to address
# A603 on 3 bytes, then we win in 256
B!
Unfortunately, the macro does not work
when compiling the top of memory - no paging ORG default
compiles zero. [This paper was written long ago, and for ALASM
4.46 This remark is no longer valid.]
Sometimes it happens that on one disc contains several
projects. And part of the source files belong to multiple
projects and dependence may be the most zaputannymi.Inogda
there are cases when one The same file is included several
times. To avoid this problem once and for all
protect themselves from further head
pain, prepare files as follows:
IFN? _UNIQUE_NAME_; Early File
_UNIQUE_NAME_ = 0
...
ENDIF; at the end of file
You guessed it, _UNIQUE_NAME_
must be unique for each file.
Works are all very prosto.Esli include file is not found in
space Tag your ID, he announced his
and with a clear conscience kompiliruetsya.Inache he simply
skipped.
Typically, the program exists in two versions - debug and
final. Debug version, as you already understood, there is only
a programmer, which it does. The final version - this is what
goes to the user. Between these two versions can be quite a big
difference. Starting from output (in the debug version is a
return to assembler, and in the final or output in dos or
neglect) to the replacement of entire
pieces of code. How to do this conveniently,
not to forget in the turmoil predreliznogo
replace the appropriate lines. Very simple. In
We arrange the critical areas of the program
lines:
IFN? _DEBUG_; 0 = = tag has something
, 1 = not assigned and used
, -1 = Do not mark
... ; Release version
ELSE
... ; Debug version
ENDIF
And at the very beginning of the program write the line:
_DEBUG_
With its release just need to comment out. "Reaction" at the
source code version may be the most raznoy.Eto can be a
reminder of the test version of the program, the output of
diagnostic messages, etc.
ALASM from version 4.46 supports the unclosed parentheses
conditional compilation macros, so the above examples can be
slightly modified to create a macro:
MACRO IFDEF
IF?
ENDM
MACRO IFNDEF
IFN?
ENDM
How to apply them, I think, you guessed it:)
Working with sets.
Sometimes there is a problem storing sets of discrete data,
for example, a set of vowels or consonants bukv.Vyvesti pattern
is difficult, therefore it is necessary to prescribe the data.
Usually given a table and search for it is through Team CPIR or
similar. But spend a byte to the fact of the presence of the
element rather expensive, because you can in this case to spend
a bit. Below text macro, which allows to automate work with
sets.
When defining the set of macro transmit Xia options:
- The address of the bitmap (as determined by the dynamical);
- Minimum and maximum values;
- The initial set.
First example file:
INCLUDE "MAKESET", 199
ORG 24576
; Empty
MAKESET SET1, "A", "B", ""
And the set of two letters
MAKESET SET2, "B", "Z", "CD"
ORG 24576; sure!
And the text of the macro:
MACRO MAKESET
; MAKESET NAMESET, MIN, MAX ,....
DS 2-1 +8' # FFF8> 3
IF? BITOPER +1
BITOPER RRA
RR L
RRA
RR L
RRA
RR L
RRA
RRA
BITOPA OR # 46
LD (BITOP +1), A
BITOP DB # CB, 0, $ 1
RET
ENDIF
_MIN
= 1
_MAX
= 2
ADD
LD L, A
LD A, # C6
JR
OP
DEL
LD L, A
LD A, 86
JR
OP
ISIN
LD L, A
LD A, # 46
OP LD (BITOPA +1), A
LD A, L
IFN a
SUB 1
RET C
ENDIF
CP 2-1
JR Z, $ +4
CCF
RET C
; HERE
LD H, '
IFN
'31
ADD A,
'31 <3
ENDIF
LD L, A
IFN
'7
LD A,
'7
ELSE
XOR A
ENDIF
JP BITOPER
LOCAL
_OLDADR = $
DUP 3
REPEAT
UNTIL "NC" -44
EDUP
IFN "NNC" -34
REPEAT
ORG "C" -1 '# FFF8> 3 +
IFN "C" -1 <1'1
DISPLAY "SYMBOL C IS OUT OF RANGE
ENDIF
IFN 2 - "C" <1'1
DISPLAY "SYMBOL C IS OUT OF RANGE
ENDIF
DB {$}|( 1 <("C" -1 '7))
UNTIL "NC" -34
ENDIF
ORG _OLDADR
ENDL
ENDM
As you can see, you also create the necessary code for the
modification sets and determine the presence of elements.
If the set is named SET1, then the operations
will be respectively the names ADDSET1,
DELSET1, ISINSET1. If you only need
procedure to check the rest can not generate.
Most programmer trick:)
You already used that macros typically perform passive
functions, managing the compilation and warning. But how can
they be get to do the work. Below
example of macro libraries, which are not
making a single byte of object code, creates the file
disassembler given region memory. Explains the specificity of
the macro huge and complex "code" (as well as the accumulation
of knowledge in the creation of this sources and lazy to fix
the old implementation:)).
Because of the "wildcard" algorithm processing macros ALASM
4.46f Library very slow in this version alasma [just in it!],
so it is better to start earlier [or later] versions of the
assembler.
Here is a sample file that demonstrates the work that
libraries:
INCLUDE "mDASM", # C4
ORG 24576
; _DEC; Inclusion of the decimal system
; _VERBOSE; Display the current address
DISASM "TESTA", # C0, 0,149
In this case, page # C0 creates a file named TESTA,
containing the disassembler code ROM at address 0 and a length
of 149 bayt.Fayl simply otkompilirovat.Zapuskat nothing.
But that was the result:
; This file was created by mDASM.
; (C) Vitamin/CAIG/2001 all rights reserved
L00000 DI
XOR A
LD DE, # FFFF
JP # 11CB
L00008 LD HL, (# 5C5D)
LD (# 5C5F), HL
JR $ + # 45
L00016 JP # 15F2
L00019 RST # 38
RST # 38
RST # 38
RST # 38
RST # 38
LD HL, (# 5C5D)
LD A, (HL)
CALL # 007D
RET NC
CALL # 0074
JR $ - # 07
L00037 RST # 38
RST # 38
RST # 38
JP # 335B
L00043 RST # 38
RST # 38
RST # 38
RST # 38
RST # 38
PUSH BC
LD HL, (# 5C61)
PUSH HL
JP # 169E
L00056 PUSH AF
PUSH HL
LD HL, (# 5C78)
INC HL
LD (# 5C78), HL
LD A, H
OR L
JR NZ, $ + # 05
INC (IY + # 40)
PUSH BC
PUSH DE
CALL # 386E
POP DE
POP BC
POP HL
POP AF
EI
RET
L00083 POP HL
LD L, (HL)
LD (IY), L
LD SP, (# 5C3D)
JP # 16C5
L00095 RST # 38
RST # 38
RST # 38
RST # 38
RST # 38
RST # 38
RST # 38
PUSH AF
PUSH HL
LD HL, (# 5CB0)
LD A, H
OR L
JR NZ, $ + # 03
JP (HL)
L00112 POP HL
POP AF
RETN
L00116 LD HL, (# 5C5D)
INC HL
LD (# 5C5D), HL
LD A, (HL)
RET
L00125 CP # 21
RET NC
CP # 0D
RET Z
CP # 10
RET C
CP # 18
CCF
RET C
INC HL
CP # 16
JR C, $ + # 03
INC HL
SCF
LD (# 5C5D), HL
RET
As can be seen, the code turns out not
relotsiruemyy.Realizatsiya replace all addresses labels would
require another pass through the code, would increase and so
much processing time. For example, when processing the above
piece of code length of 149 bytes were counted more than 50
thousand rows. Row Count can fill up a few times before
What do you get a result.
Finally, the text of the library. [Basic
fragmentov.Polnostyu look in the appendix.]
MACRO digit
IF
-10 <1'1
DB
+55
ELSE
DB
+ "0
ENDIF
ENDM
MACRO itoa; $ = ADDR
IF? _DEC +1
DB "#
digit
<4'15
digit
<8'15
digit
> 4'15
digit
'15
ELSE
LVAL =
digit LVAL/10000
LVAL = LVAL-(LVAL/10000 * 10000)
...
digit LVAL/10
LVAL = LVAL-(LVAL/10 * 10)
digit LVAL
ENDIF
ENDM
MACRO btoa
And the same, but for a byte
ENDM
MACRO offset
IF
<1'1
DB "+
btoa
ELSE
DB "btoa -
ENDIF
ENDM
MACRO offs
LVAL =
'128 * 511 |
offset LVAL
ENDM
MACRO hl
IFN _IX
DD E4; IX
ELSE
IFN _IY
DD E5; IY
ELSE
DD E2
ENDIF
ENDIF
ENDM
MACRO hl_l
, Similarly for the LX / LY / L
ENDM
MACRO hl_h
, Similarly for the HX / HY / H
ENDM
MACRO _hl_
LOCAL
IFN _IX
_FROM = _FROM +1
_LOFF =. {_FROM}
_SIZE = _SIZE-1
IFN _LOFF
DD D1; (IX
offs _LOFF
DB ")
ELSE
DD A3; (IX)
ENDIF
ELSE
IFN _IY
, And similarly for (IY + d)
ELSE
DD A1; (HL)
ENDIF
ENDIF
ENDL
ENDM
MACRO lrpNN
DD D4
IF
- # E2
hl
ELSE
DB
ENDIF
DB ",
itoa {_FROM +1}
_OPSIZE = _OPSIZE +2
ENDM
MACRO selreg
IFN
-4 <1'1
DB
+ # EF; B, C, D, E
ENDIF
IF
-4
hl_h; H
ENDIF
...
ENDM
MACRO selop
[IF .. ELSE: IF .. ELSE: IF .. ENDIF: ENDIF: ENDIF
compiled no faster than several IF
.. ENDIF, and the stack takes place anymore.
4 bytes on the IF. ]
IF
-7
DD D8; CP
ENDIF
...
IF
DD AEF52C; ADD
ENDIF
ENDM
MACRO operCB
IF
DD B8; RLC
ENDIF
...
ENDM
MACRO operED; lda, rp, rh
IF
; IN r, (C)
IF 2 - # F5
DD CE; INF
ELSE
DB # DC, February ,",",# D0
ENDIF
ENDIF
...
IF
-15
...
ENDIF
ENDM
MACRO flag
IF
DD E7; NZ
ENDIF
...
IF
-7
DD F7; M
ENDIF
ENDM
;----------------------------------------
MACRO DISASM
...
_FROM = 2
_SIZE = 3
ORG # C000, 1
_MNAME DB S,
IFN $-_MNAME-8
DS 8 - $ + _MNAME, 1932
ENDIF
DB "H
DS 24
_HSIZE DW 0, # C040
DB 0,0
DB 1
DD F376C7DDFDEDB0D9; key ALASM
DS 16
_TXTSTART
DB 1933, "; This file was created by mDASM."
DB 1943, "; (C) Vitamin/CAIG/2001"
DB "all rights reserved"
_SETLAB = 1, start with the source tags
REPEAT; main loop
_STRLEN = $
DB 0
; SET LABEL
IFN _SETLAB
ORG $ -1
DB 1
_STRLEN = $
DB 0, "L
LVAL = _FROM
digit LVAL/10000
LVAL = LVAL-(LVAL/10000 * 10000)
...
digit LVAL
_SETLAB = 0
ENDIF
_DA =. {_FROM}
_OPSIZE = 1
_IX = 0
_IY = 0
REPEAT
_SETXY = 0
IFN? _VERBOSE +1
DISPLAY _FROM
ENDIF
IF _DA-# DD
_IX = 1; IX PREFIX
_IY = 0
_FROM = _FROM +1
_SIZE = _SIZE-1
_DA =. {_FROM}
_SETXY = 1
ENDIF
IF _DA-# FD
_IY = 1 ... ; IY PREFIX
ENDIF
UNTIL _SETXY
IF _DA
DD A5; NOP
ENDIF
IF _DA-1
lrpNN # E0; LD BC, nn
ENDIF
...
IF _DA-6
DD D4EF2C; LD B, n
btoa. {_FROM +1}
_OPSIZE = _OPSIZE +1
ENDIF
...
_DA = _DA-16
IF _DA
DD 8B24; DJNZ
offs. {_FROM +1} +2
_OPSIZE = _OPSIZE +1
ENDIF
...
_DA = _DA-16
...
IF _DA-2
DD D428; LD (nn), HL
itoa {_FROM +1}
DB "),
hl
_OPSIZE = _OPSIZE +2
ENDIF
...
IF _DA-9
DD AE; ADD HL, HL
hl
DB ",
hl
ENDIF
...
_DA = _DA-16
...
_DA = _DA-16
IF _DA'192
IF _DA-# 36
DD 86; HALT
ELSE
DD D4
IFN _IX
IF _DA'56> 3-6
selreg _DA'56> 3
_IX = 0
ELSE
IF _DA'7-6
_IX = 0
ENDIF
selreg _DA'56> 3
_IX = 1
ENDIF
ELSE
IFN _IY
; Similarly, but instead of IY IX
ELSE
selreg _DA'56> 3
ENDIF
ENDIF
DB ",
selreg _DA'7
ENDIF; 36
ENDIF; 192
_DA = _DA-64
IF _DA'192
selop _DA'56> 3
selreg _DA'7
ENDIF
_DA = _DA-64
IF _DA'192
IF _DA'7
DD B4; RET
flag _DA> 3'7
ENDIF
...
IF _DA'7-3
_PAR = _DA> 3'7
...
IF _PAR-1; CB
LOCAL; # # #
... ; Tricky handling # CB
ENDL; ***
ENDIF; CB
...
ENDIF
...
IF _DA'7-5
_PAR = _DA> 3'7
...
IF _PAR-5; ED
LOCAL; # # #
... ; Tricky handling # ED
ENDL; # # #
_OPSIZE = _OPSIZE +1
ENDIF; ED
...
ENDIF
...
ENDIF
; STRING FINISH
_STRSIZ = $-_STRLEN
_OLDADR = $
ORG _STRLEN
DB _STRSIZ
ORG _OLDADR
_SIZE = _SIZE-_OPSIZE
_FROM = _FROM + _OPSIZE
UNTIL ~ _SIZE <1 ~ '1; end of Chap. cycle
NOP; an end-source code
_TEXTSIZ = $-_TXTSTART
ORG _HSIZE, a
DW _TEXTSIZ
ORG 82; not to run on the RUN
ENDM; end macro DISASM
Vitamin/CAIG/2001
Other articles:
Similar articles:
В этот день... 14 November