From 092bb23f5d0ad969720653e1bae5f147b509b7cd Mon Sep 17 00:00:00 2001 From: kio Date: Wed, 8 Jan 2020 17:26:45 +0100 Subject: [PATCH 1/3] new: literal text replacement of expressions in macros --- Linux/zasm.pro | 1 + Source/Source.cpp | 2 + Source/Z80Assembler.cpp | 22 ++++- Source/main.cpp | 4 +- Test/Z80/callstack.asm | 165 ++++++++++++++++++++++++++++++++ Test/Z80/original/callstack.rom | Bin 0 -> 156 bytes 6 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 Test/Z80/callstack.asm create mode 100644 Test/Z80/original/callstack.rom diff --git a/Linux/zasm.pro b/Linux/zasm.pro index 27fddbe..71522f6 100644 --- a/Linux/zasm.pro +++ b/Linux/zasm.pro @@ -63,6 +63,7 @@ HEADERS += \ Source/Segment.h \ Source/settings.h \ Source/Source.h \ + Source/Value.h \ Source/zx7.h \ Source/SyntaxError.h \ Source/Z80Assembler.h \ diff --git a/Source/Source.cpp b/Source/Source.cpp index 92dbb24..d7e7fb9 100644 --- a/Source/Source.cpp +++ b/Source/Source.cpp @@ -183,6 +183,8 @@ cstr SourceLine::nextWord () case ')': return ")"; case ',': return ","; case '=': return "="; + case '{': return "{"; + case '}': return "}"; case '\'': // 'abcd' ''' or '' if (*p==c) { p++; if (*p!=c) return "''"; p++; return "'''"; } // special test for ''' diff --git a/Source/Z80Assembler.cpp b/Source/Z80Assembler.cpp index 990d346..9a5e4fa 100644 --- a/Source/Z80Assembler.cpp +++ b/Source/Z80Assembler.cpp @@ -2151,7 +2151,7 @@ void Z80Assembler::asmMacroCall (SourceLine& q, Macro& m) throws { SourceLine& s = zsource[i]; - for (int32 j=0;;j++) // loop over occurance of '&' + for (ssize_t j=0;;j++) // loop over occurance of '&' { cptr p = strchr(s.text+j,m.tag); // at next '&' if (!p) break; // no more '&' @@ -2166,9 +2166,25 @@ void Z80Assembler::asmMacroCall (SourceLine& q, Macro& m) throws // w is the name of argument #a // it was found starting at p+1 in s.text (p points to the '&') - j = p + strlen(rpl[a]) - s.text; - s.text = catstr(substr(s.text,p), rpl[a], s.p); + j = p + strlen(rpl[a]) - s.text; // calculate index j after text replacement + s.text = catstr(substr(s.text,p), rpl[a], s.p); // … because this reallocates s.text! } + + // calculate and replace values between '{' and '}' with plain text: + // e.g. for calculated label names in macros. + for (ssize_t j=0;;j++) // loop over occurrences of '{' + { + cptr p = strchr(s.text+j,'{'); // at next '{' + if (!p) break; // no more '{' + s.p = p+1; // set the parser position behind '{' + Value v = value(s, pAny); // get the value + s.expect('}'); + if (!v.is_valid()) throw syntax_error("value must be valid in pass 1"); // because replacement is done in pass 1 + cstr rpl = numstr(v.value); // textual replacement + j = p + strlen(rpl) - s.text; // calculate index j after text replacement + s.text = catstr(substr(s.text,p), rpl, s.p); // … because this reallocates s.text! + } + s.rewind(); // superflux. but makes s.p valid } diff --git a/Source/main.cpp b/Source/main.cpp index 02510b6..436cbd7 100644 --- a/Source/main.cpp +++ b/Source/main.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) Günter Woigk 1994 - 2019 +/* Copyright (c) Günter Woigk 1994 - 2020 mailto:kio@little-bat.de This file is free software @@ -51,7 +51,7 @@ static const char version[] = "4.2.5"; // static const char help[] = "–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––\n" -" zasm - z80/8080 assembler (c) 1994 - 2019 Günter Woigk.\n" +" zasm - z80/8080 assembler (c) 1994 - 2020 Günter Woigk.\n" " version %s, %s, for %s.\n" // version, date, platform " homepage: https://k1.spdns.de/Develop/Projects/zasm/\n" " send bug reports to: kio@little-bat.de\n\n" diff --git a/Test/Z80/callstack.asm b/Test/Z80/callstack.asm new file mode 100644 index 0000000..5dac083 --- /dev/null +++ b/Test/Z80/callstack.asm @@ -0,0 +1,165 @@ +#!/usr/local/bin/zasm -o original/ + + ORG $0000 + +_STACK_SIZE DEFL 0 +_PARAM_COUNT_0 DEFL 0 ;Redefinable labels initialization + + +;Adds the content of ® to the stack and increment the _PARAM_COUNT_0 label. + MACRO _ADD_PARAM ® + PUSH ® +_PARAM_COUNT_0 DEFL {_PARAM_COUNT_0+1} + ENDM + +;Adds a litteral 16 bits parameter to the stack then increment the +;_PARAM_COUNT_0 label. Register values are preserved. + MACRO _ADD_LPARAM &lit + PUSH HL + LD HL,&lit + EX (SP),HL +_PARAM_COUNT_0 DEFL {_PARAM_COUNT_0+1} + ENDM + +;Macro that calls a procedure &proc. This macro cleans the stack from the +;parameters added with _ADD_PARAM or ADD_LPARAM. Register HL and DE may be +;changed if the subroutine returns respectively a 16 or 32 bits value. + MACRO _CALL &proc + _PUSH_STACK + CALL &proc + _POP_STACK + _CLEAN_PARAMS {_PARAM_COUNT_0} +_PARAM_COUNT_0 DEFL 0 + ENDM + +;Increments the _STACK_SIZE label and shift _PARAM_COUNT_# labels value to +;_PARAM_COUNT_#+1, up to _PARAM_COUNT_{STACK_SIZE}, then save all the Z80 +;registers on the stack. + MACRO _PUSH_STACK +_STACK_SIZE DEFL {_STACK_SIZE+1} + _SHIFT_STACK {_STACK_SIZE+1} + CALL _PUSH + ENDM + +;Shift _PARAM_COUNT_# values up the stack. + MACRO _SHIFT_STACK &cnt + IF &cnt > 0 +_PARAM_COUNT_{&cnt} DEFL _PARAM_COUNT_{&cnt-1} +_PARAM_COUNT_{&cnt-1} DEFL 0 + _SHIFT_STACK {&cnt-1} + ENDIF + ENDM + +;Shift _PARAM_COUNT_# down the stack and then restores Z80 registers. Then +;decrement _STACK_SIZE label. + MACRO _POP_STACK + _UNSHIFT_STACK _STACK_SIZE +_STACK_SIZE DEFL {_STACK_SIZE-1} + CALL _POP + ENDM + +;Shift _PARAM_COUNT_# values down the stack. + MACRO _UNSHIFT_STACK &cnt + IF &cnt > 0 +_PARAM_COUNT_{&cnt-1} DEFL _PARAM_COUNT_{&cnt} +_PARAM_COUNT_{&cnt} DEFL 0 + _UNSHIFT_STACK {&cnt-1} + ENDIF + ENDM + + +;Macro that cleans &count parameters from the stack. + MACRO _CLEAN_PARAMS &cnt + IF &cnt > 0 + EX (SP),HL + POP HL + _CLEAN_PARAMS {&cnt-1} + ENDIF + ENDM + + +;Loads the register ® with the parameter at index &idx +;Since IY is used to get at parameters, its not possible to load +;a parameter into IY using this macro. + MACRO _GET_PARAM ®, &idx + LD IY,14 + ADD IY,SP + LD ®, (IY+{&idx*2}) + ENDM + + +;Return the content of ®1 at the stack position of HL. The content of IY +;can not be returned using this macro. + MACRO _RET_HL ®1 + LD IY,0 + ADD IY,SP + LD (IY+12),®1 + RET + ENDM + + + +;Return the content of ®1 at the stack position of HL and the +;content of ®2 at the DE stack position. The content of IY canot +;be returned by this macro. + MACRO _RET_HLDE ®1, ®2 + LD IY,0 + ADD IY,SP + LD (IY+12),®1 + LD (IY+10),®2 + RET + ENDM + + +;Save all registers +_PUSH: EX (SP),HL + PUSH DE + PUSH BC + PUSH AF + PUSH IY + PUSH IX + PUSH HL + RET + + +;restore all registers +_POP: POP HL + POP IX + POP IY + POP AF + POP BC + POP DE + EX (SP),HL + RET + + +; *** Actual test starts here *** + + _ADD_LPARAM 6 ;param 2 + _ADD_LPARAM 5 ;param 1 + _CALL EXP + +LOOP: JR LOOP + + +;Make parameter 1 exponent parameter 2. I.E. Param1 is the base and param2 +;is the exponent. Returns value in HL. +EXP: _GET_PARAM DE,1 ;base + _GET_PARAM HL,1 ;initialize HL with base + _GET_PARAM BC,2 ;exponent +EXP_1: _ADD_PARAM DE + _ADD_PARAM HL + _CALL MUL + DEC BC + JR NZ,EXP_1 + _RET_HL HL + + +;Multiply parameter 1 with parameter 2. Returns result in HL. +MUL: _GET_PARAM DE,1 + _GET_PARAM BC,2 + LD HL,0 +MUL_1: ADD HL,DE + DEC BC + JR NZ,MUL_1 + _RET_HL HL diff --git a/Test/Z80/original/callstack.rom b/Test/Z80/original/callstack.rom new file mode 100644 index 0000000000000000000000000000000000000000..07dabcd60d11e9ace35a7c35aa4ba82d7a0fd936 GIT binary patch literal 156 zcmaES_2}2XPwzf`dh+4jhkqY_Jb3Z($)}2J43D2GvNAkA%fN6}m*FfI!{djKA4>fD ztH{Uj*Ya;1)88;=C_9hoZyJp4$MV;W_3BfQrUIBIZiRP$6&XOfN_qa4@SenC1XvqT LjU>0i9~89!3usKL literal 0 HcmV?d00001 From 835435fb44b2d443b8b10ef5776b149f725c9ae2 Mon Sep 17 00:00:00 2001 From: kio Date: Wed, 8 Jan 2020 17:42:54 +0100 Subject: [PATCH 2/3] updated documentation --- Documentation/Version History.txt | 14 +++++++-- Documentation/automate.vs | 0 Documentation/index.html | 4 +-- Documentation/macro endm.txt | 48 ++++++++++++++++++++++--------- 4 files changed, 49 insertions(+), 17 deletions(-) mode change 100644 => 100755 Documentation/automate.vs diff --git a/Documentation/Version History.txt b/Documentation/Version History.txt index 23de5ce..4196cf6 100644 --- a/Documentation/Version History.txt +++ b/Documentation/Version History.txt @@ -36,5 +36,15 @@ pre 1.0.0 1996: First version for private use. Mac OS 7.0. No public release. 4.0.20 2017: minor rework of c-compiler handling, bug fixes 4.0.21 2017: allow multiple opcodes per line after '\' 4.0.24 2017: define NAME_size and NAME_end labels for all segments - 4.1.0 2017: included Einar Saukas' ZX7 "optimal" LZ77 compressor - \ No newline at end of file + 4.1.0 2017: included Einar Saukas' ZX7 "optimal" LZ77 compressor + 4.1.2 2017: fixed problems with compressed size validity + 4.1.3 2017: new function sin() and cos() to easily build wave tables + 4.1.4 2017: added pseudo instructions DUP and EDUP as an alias for REPT and ENDM + 4.1.5 2017: reworked the regression test framework. Added support for '#!' in line 1 of the source file + 4.2.0 2018: new #target TZX: directly write to .tzx tape files + 4.2.1 2018: Bug fixes. This was to be expected. + 4.2.2 2018: Fixed bug where the binary file was appended to the hex or s19 file + 4.2.3 2018: Fixed bug where error messages were garbled + 4.2.4 2019: Fixed bug in .rept/.endm or .dup/.edup sanity check + 4.2.5 2020: added text replacement in macros for values between '{' and '}'. + diff --git a/Documentation/automate.vs b/Documentation/automate.vs old mode 100644 new mode 100755 diff --git a/Documentation/index.html b/Documentation/index.html index 0409004..9a64b4f 100644 --- a/Documentation/index.html +++ b/Documentation/index.html @@ -20,7 +20,7 @@ <--  back   - Last regenerated: 2018-05-27 22:10:33 kio + Last regenerated: 2020-01-08 17:18:33 kio @@ -43,7 +43,7 @@

Table of Contents

Targets

List File

Legal and Version History

-

Last updated: 2018-05-27 22:10:33.

+

Last updated: 2020-01-08 17:18:33.

zasm is a multiple pass assembler for the historic 8-bit CPU Zilog Command Line Options: --z80
Pseudo instructions: .z80, .z180 and .8080
Targets: #target Z80
Z80
and it's variants, e.g. Intel 8080 (it's predecessor) or the Command Line Options: --z180
Pseudo instructions: .z80, .z180 and .8080
Z180 / HD64180
.

zasm is available for Unix-like operating systems like OSX, Linux, BSD.

Download page and Git archive:

diff --git a/Documentation/macro endm.txt b/Documentation/macro endm.txt index 4da100d..2399aea 100644 --- a/Documentation/macro endm.txt +++ b/Documentation/macro endm.txt @@ -1,13 +1,15 @@ h3 macro, .macro, endm and .endm macro, endm - -p 'macro' starts a macro definition and 'endm' terminates it. Macros are assigned a name by which they can later be used at the place of an ordinary instruction. -p There are quite numerous formats used by different assemblers and zasm tries to support at least some of them out of the box. In the following code examples the instruction names with or without a dor can be used interchangeable. +p 'macro' starts a macro definition and 'endm' terminates it. Macros are assigned a name by which they can later be used at the place of an ordinary instruction. + +p There are quite numerous formats used by different assemblers and zasm tries to support at least some of them out of the box. In the following code examples the instruction names with or without a dot can be used interchangeably. p Frequently you need some kind of label in a macro, but you cannot redefine ordinary labels. Frequently this can be solved with redefinable labels which are defined with 'defl' or 'set'. +p Since version 4.2.5 expressions between '{' and '}' are evaluated and replaced with the resulting text. This can be used to generate label names. The expression must be evaluatable in pass 1 because macro replacement is done in pass 1. + p It is possible to conditionally exclude portions of the macro by use of the pseudo instructions 'if' and 'endif'. (not '#if' and '#endif'!) p Assembler directives (starting with '#') are not allowed inside macros. @@ -15,14 +17,14 @@ p Assembler directives (starting with '#') are not allowed inside macros. h5 Define a simple macro without arguments -pre macro +pre macro ... endm - + p Alternate syntax: -pre macro +pre macro ... endm @@ -33,7 +35,7 @@ pre counter defl 0 COUNT .macro counter defl counter + 1 .endm -   +   ...   COUNT @@ -50,9 +52,9 @@ pre macro [ , … ] ... endm - + p Alternate syntax: - + pre macro [ , … ] ... @@ -61,7 +63,7 @@ pre macro [ , … ] p Invocation: pre [ , … ] - + p This defines a macro with some arguments. Either of both definition styles are possible. Additionally there are different methods for defining and referencing the symbol arguments: pre foo: macro A, B @@ -104,7 +106,7 @@ pre foo: macro &A foo 20 ... foo 8 - + p In this example the argument is used as the second argument for 'ld b,N' and to construct a unique label name for each invocation. Obviously the passed argument must be a number literal else the label name thing won't work. A better solution would have been to use a redefinable label. @@ -126,10 +128,30 @@ p Complex arguments start with an opening '<' and run up to the next '>' which i pre foo <,>, <;>, <"> ; 3 arguments: , ; and " foo <<>, < >, ; 3 arguments: < space and ld a,b foo >, ><, ; 3 arguments: > >< and nothing - + p There are still some impossible combinations, e.g. it is not possible to pass <>, (3 characters) as an argument. +h5 Evaluation and literal text replacement of expresions +p.i since versio 4.2.5 + +pre L: .equ 0 ; initialize redefinable label 'L' + + ; calculate unsigned max + ; &A = umax(&A,&B) + ; usable for a and hl. + + umax: .macro &A, &B + and a + sbc &A,&B + jr nc,L{L} ; e.g. L0 in first call + ld &A,&B + jr L{L+1} ; e.g. L1 in first call + L{L}: add &A,&B + L{L+1}: + L .equ L+2 ; next macro call will use L2 and L3 + .endm + h5 Not implemented in macros: @@ -142,7 +164,7 @@ li keyword 'local': try to use 'defl' instead. (not possible in all cases) - + From 0fc947d617bfda7c04320cf7fd6b74b94e7a3c2f Mon Sep 17 00:00:00 2001 From: kio Date: Wed, 8 Jan 2020 18:15:27 +0100 Subject: [PATCH 3/3] pushed version to 4.2.6 --- Documentation/Version History.txt | 2 +- Documentation/macro endm.txt | 4 ++-- Source/main.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/Version History.txt b/Documentation/Version History.txt index 4196cf6..6465882 100644 --- a/Documentation/Version History.txt +++ b/Documentation/Version History.txt @@ -46,5 +46,5 @@ pre 1.0.0 1996: First version for private use. Mac OS 7.0. No public release. 4.2.2 2018: Fixed bug where the binary file was appended to the hex or s19 file 4.2.3 2018: Fixed bug where error messages were garbled 4.2.4 2019: Fixed bug in .rept/.endm or .dup/.edup sanity check - 4.2.5 2020: added text replacement in macros for values between '{' and '}'. + 4.2.6 2020: added text replacement in macros for values between '{' and '}'. diff --git a/Documentation/macro endm.txt b/Documentation/macro endm.txt index 2399aea..950a83a 100644 --- a/Documentation/macro endm.txt +++ b/Documentation/macro endm.txt @@ -8,7 +8,7 @@ p There are quite numerous formats used by different assemblers and zasm tries t p Frequently you need some kind of label in a macro, but you cannot redefine ordinary labels. Frequently this can be solved with redefinable labels which are defined with 'defl' or 'set'. -p Since version 4.2.5 expressions between '{' and '}' are evaluated and replaced with the resulting text. This can be used to generate label names. The expression must be evaluatable in pass 1 because macro replacement is done in pass 1. +p Since version 4.2.6 expressions between '{' and '}' are evaluated and replaced with the resulting text. This can be used to generate label names. The expression must be evaluatable in pass 1 because macro replacement is done in pass 1. p It is possible to conditionally exclude portions of the macro by use of the pseudo instructions 'if' and 'endif'. (not '#if' and '#endif'!) @@ -133,7 +133,7 @@ p There are still some impossible combinations, e.g. it is not possible to pass h5 Evaluation and literal text replacement of expresions -p.i since versio 4.2.5 +p.i since versio 4.2.6 pre L: .equ 0 ; initialize redefinable label 'L' diff --git a/Source/main.cpp b/Source/main.cpp index 436cbd7..37b2f76 100644 --- a/Source/main.cpp +++ b/Source/main.cpp @@ -44,7 +44,7 @@ //static const char appl_name[] = "zasm"; -static const char version[] = "4.2.5"; +static const char version[] = "4.2.6"; // Hilfstext: // Anzeige optimiert für 80-Zeichen-Terminal