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:
В этот день... 3 February