String comparison procedure in Z80 assembler
ZXNet echo conference «code.zx»
From Ivan Roshin → To All 5 July 2003
Hello, All!
═══════════════════ cmp_str .t ══════════════════
(c) Ivan Roshchin, Moscow
Fido: 2:5020/689.53
ZXNet: 500:95/462.53
E-mail: bestview@mtu-net.ru
WWW: http://www.ivr.da.ru
String comparison procedure in Z80 assembler
═════════════════════ ══════════════════════
("Radiomir. Your computer" 6/2003)
When writing the BestView program, I needed a procedure
comparing two strings with the following input and output
parameters: in HL the address of the first line is specified, in DE - the address
the second line, in BC - the length of the line (not equal to 0); output flag
Z is set if the lines match, and cleared otherwise.
The string comparison algorithm is very simple: we take bytes by
address specified in DE, compare it with the byte at the address
specified in HL, in case of inequality, we exit the procedure
(flag Z is cleared), in case of equality, increase HL and
DE by 1 (so they will now point to the following
bytes of the compared strings) and decrease BC by 1 (i.e. decrease
counter); if after decreasing BC<>0, proceed to comparison
next bytes, otherwise (BC=0) the lines match, then we exit
procedures (the Z flag is set).
Accordingly, I wrote a procedure that
used in BestView up to version 2.14 inclusive:
COMP_ST LD A,(DE)
CP(HL)
RET NZ ;Do not match.INC HL ;!
INCDE ;!
DEC BC ;!
LD A,B ;!
OR C ;!
JR NZ,COMP_ST
RET ;Coincid.
And recently, while looking through it, I noticed this:
that: increase HL and DE by 1, decrease BC by 1, check BC by
equality to zero - but in the instruction system of the Z80 processor there is
the team that does it all!
The LDI instruction copies a byte from (HL) to (DE), increments HL and
DE by 1, decrease BC by 1, reset P/V flag if after
decreases BC=0, and sets the P/V flag otherwise.
That is, this command does almost the same as the marked one
"!" fragment of the procedure, only, firstly, also copies a byte from
(HL) into (DE), and secondly puts information about the equality of BC
zero to the P/V flag, not to the Z flag.
Copying a byte from (HL) to (DE) in the procedure in question
completely useless. However, if you look more closely, you can
notice that after the RET NZ command, a byte is at the address specified in
HL, obviously equal to the byte at the address specified in DE
(indeed, if they were not equal, then after comparing them
the procedure would exit).
And if the bytes are equal, then copying from (HL) to (DE) is not
will change (DE), that is, it will be a harmless side effect.
Then the entire section of the procedure marked "!" can be replacedby one LDI command, simultaneously replacing the conditional command
go to the beginning of the cycle (JR NZ,COMP_ST) to the command
JP PE,COMP_ST - after all, now it is the P/V flag that indicates
fulfillment or failure of the condition BC=0.
But one more problem remains: when exiting the procedure in
If the strings match, the Z flag must be set. And if
in the original version of the procedure it was automatically
set when checking the loop exit condition (BC=0), then
Now the check for this condition is not associated with the Z flag at all.
First I wanted to add before exiting the procedure in case
line matches (i.e. before the last RET command) command
XOR A, which sets the Z flag. But, after looking in the reference book, I
saw that the LDI command does not change the Z flag, but looking at
procedure, I saw that after comparing the next bytes of the strings
the Z flag will definitely be set (after all, the lines match!). So
Thus, nothing special needed to be added.
So, an optimized version of the procedure:
COMP_ST LD A,(DE)
CP(HL)
RET NZ ;Do not match.
LDI ;Ha Z has no effect!
JP PE,COMP_ST
RET ;Coincident, Z=1!
The length of the procedure decreased by 2 bytes, and the execution time
reduced as follows: in the case when compared
the strings do not match (and their first n bytes match),the gain is 12n cycles, and in the case when the lines
coincide (n is their length), the gain is 12(n-1)+7 cycles.
════════════════════════ ════════════════════════
Best regards, Ivan Roshchin.
From Kirill Frolov → To All 14 July 2003
Press RESET immediately, Ivan Roshin!
IR> ("Radiomir. Your computer" 6/2003)
IR> When writing the BestView program, I needed a procedure
IR> comparing two strings with the following input and output
It would be better if someone wrote a quick procedure for parsing regular expressions
having the function of fuzzy comparison of strings (with texts in Russian
otherwise it’s difficult), in Z80 assembler. I haven’t seen it anywhere, but it’s a useful thing for
searching for something in the text, for parsing, etc...