Deja Vu #08
31 мая 1999

CODING - an undocumented feature of the processor Z80.

<b>CODING</b> - an undocumented feature of the processor Z80.
AY-Track: Muzic theme from game "FAIRLIGHT"
__________________________________________


(C) Ivan Roshchin
__________________________________________



     Undocumented feature

             CPU Z80



   Allowed free
This article provided no kakihlibo make changes and save my 
copyright. 

1. How it all began



   I wrote once the next version of the program BestView (v2.4) 
and used it Here's a snippet:



      ....

      EI

      CALL SUBR1

      HALT

      ....


SUBR1 LD A, R

      PUSH AF

      DI



      ....



      POP AF

      DI

      RET PO

      EI

      RET



   In the snippet is a procedure call SUBR1, which at the time 
of his work disables the interrupts, while output recovers the 
previous regime of their work. 


   Verifying that are allowed or disallowed
interruption in the procedure call, and restore interrupt mode 
is as follows: 

 - The team LD A, R enters into a flag P / V coc
   Toyan trigger interrupt IFF2;
 - Register pair AF is stored in the degree
   Ke (PUSH AF);
 - Do not Interrupt (DI);
 - Are satisfied, in fact, the functions for

   which was designed and procedure

   SUBR1;
 - The contents of AF recovered (POP

   AF);
 - Interrupts are prohibited (DI);
 - If the flag P / V reset is exited

   of the procedure prohibited by interrupting
   mi (RET PO);
 - Or exits to the allowed

   Interrupt (EI: RET).



   I began to notice that when running this
fragment BestView hangs - not always, and
not even too often, but in very rare
cases. But still, it was not very
nice. The program, like, did not contain
no errors, at least at first
See anything suspicious, I did not notice. Had only to resort 
to more a powerful tool ...


2. The situation begins to brighten



   After another hang-up, I put
a blank disk and confidently pressed the MAGIC.
Then loaded the debugger "STS 6.2 + @" (not
I reworked it for nothing - now using it after downloading @ 
file, you can restore the contents of CPU registers on the 
instant relief to disk). Pressure a pair of keys - and now I 
see where in the program crash happened.


....
EI
CALL SUBR1
HALT <------------ here!
....



   A typical case - Interrupt prohibited
and the processor has stopped execution of the program
on the command HALT. But why break proved to be forbidden - it 
is not clear. After all, before calling the procedure SUBR1 
they were allowed Team EI, and after work

SUBR1 they too should be allowed SUBR1-procedure should not 
affect on the mode of their work.


   They trace SUBR1. Everything goes as expected
- And at the entrance and exit interrupts are allowed. Repeat 
trace: once, twice ... tenth. Everything is going fine.


   And maybe the fact that SUBR1
something happens with the stack? And because of this
sometimes incorrectly restored the contents of AF? We ought to 
check out ... 

3. Hanging: double second



   Well, rewrote the program. Now there
I'll know exactly what it was:

SUBR1 LD A, R

      PUSH AF

      DI



      PUSH HL

      PUSH AF

      POP HL

      LD (WR_HH1), HL

      POP HL



      ....



      POP AF



      PUSH HL

      PUSH AF

      POP HL

      LD (WR_HH2), HL

      POP HL



      DI

      RET PO

      EI

      RET


WR_HH1 DW 0
WR_HH2 DW 0



   The contents of AF now remembered not
only in the stack, but in variable WR_HH1
(Control), and at the exit from the procedure
- Removal from the stack value is stored in
WR_HH2. If the procedure works correctly,
WR_HH1 and WR_HH2 must match, and the flag
P / V to be installed.

   Run ... For a moment BestView works fine ... Look through 
with it the same file, while viewing that it hung the last time 
... Well, again! And no wonder, because the reason I

not eliminated. Okay, we understand.

   Again, press MAGIC, load "STS 6.2
+ @ ", And immediately check the value and WR_HH1
WR_HH2. And there, and there is written # 5908. Values ​​are 
the same - hence, when working with a stack of errors was not. 
But if the flags register contains # 08 - hence the flag P / V 
is reset, and the procedure call SUBR1 interrupts were 
prohibited. 

   But it's absolutely impossible! Indeed, in
program is EI: CALL SUBR1! Probably
Spectrum just overheated and because such
glitches. Nothing is more intelligent I am in this day
never came up.

4. False scent



   The next day I found a possible
explanation for the mysterious Prohibition interrupts. Suppose, 
after the team EI, but before command LD A, R, there was an 
interruption. As is known, the procedure for its treatment must 
end teams EI: RET (because in the beginning of treatment there 
is an automatic ban on interrupts). If the interrupt handler 
completes the team just RET, then the interrupt remain 
prohibited. 

   Of course, the likelihood that an interrupt will occur 
precisely between the teams and EI LD A, R is very small, but 
you and lag are very rare. So it's an extra just confirmed my 
hypothesis. 

   Nevertheless, it was unclear why would this hook ended with
command RET, but not EI: RET. I decided to check whether this 
is the whole thing, and for this added after the command HALT EI

(See below). If the interrupt handler did not completed 
successfully, then after adding HALT'a interrupts are always 
will be prohibited and, accordingly, BestView will always hang. 


      ....

      EI

      HALT <------ add commands

      CALL SUBR1

      HALT

      ....



SUBR1 LD A, R

      PUSH AF

      DI



      ....



      POP AF

      DI

      RET PO

      EI

      RET



   Compile, run ... An unexpected result - hangs completely
stopped! Like everything and leave, but
he decided to find out why this happens.

5. Acceptance of "simplification program



   When finding an error by conventional means
can not, I delete all of the programs that
possible, but that the error in this case remained. As a 
result, when the program is with a dozen lines, the error is 
noticeable immediately. So I entered and this time:



      ORG # 6000



      EI


M1 CALL SUBR1

      JR M1


SUBR1 LD A, R

      DI

      JP PO, M2

      EI

      RET
M2 LD A, 4

      OUT (254), A

      RET



   That such a program, a total of 19 bytes.
Allowed interruption and in an infinite
loop procedure is called SUBR1. This procedure sets the green 
border, if at the entrance to her termination was prohibited,

and does not change the color of the border, if the interruption
allowed. Thus, if an
spontaneous ban interrupt
it will be immediately noticeable.


   Run - yes, border changes color
to green. The reason for this strange behavior of the program 
remains unknown. Perhaps this fault interrupt handling routine 
one of the first kind? Add to Playing multiple teams, setting 
IM 2 mode with a handler, which consists only two commands: EI: 
RET. 



      ORG # 6000



      LD HL, # 8000

      LD (HL), # 81

      LD DE, # 8001

      LD BC, # 100

      LDIR

      LD A, # 80

      LD I, A

      IM 2



      EI


M1 CALL SUBR1

      JR M1


SUBR1 LD A, R

      DI

      JP PO, M2

      EI

      RET
M2 LD A, 4

      OUT (254), A

      RET



      ORG # 8181



      EI

      RET



   Run - the same result! Although the
tracing, and this and the previous program
in the debugger border is black. Careful examination of the 
program leads to hypothesis: maybe the team LD A, R

sometimes sets a bit P / V as if the interruption is prohibited 
while on Indeed, they allowed?


6. Is the error in the processor?



   Once again change the program. Now do not interrupt will be 
banned (removed command DI). If when you run LD A, R-bit P / V 
becomes equal to 0, for some time border is green (for This 
provides for the delay): 


      ORG # 6000



      LD HL, # 8000

      LD (HL), # 81

      LD DE, # 8001

      LD BC, # 100

      LDIR

      LD A, # 80

      LD I, A

      IM 2



      EI


M1 CALL SUBR1

      JR M1


SUBR1 LD A, R

      RET PE



      LD A, 4

      OUT (254), A

      LD HL, 0

      LD DE, 0

      LD BC, # 600

      LDIR; WAIT

      XOR A

      OUT (254), A

      RET



      ORG # 8181



      EI

      RET



   Run ... And what I see? Upper part
border'a flashes green:



   This suggests that, firstly, the team LD A, R do sometimes 
incorrectly sets bit P / V, and secondly - what

this is happening at the moment of arrival interrupt, but not 
when you want (indeed, then it would blink green border in a 
completely random locations).


   The fact that the upper part border'a flashes
and not always painted in green,
also receives an explanation. Apparently, the team LD A, R is 
not working only when the impulse to interrupt comes during its 
execution, as it happens not always - an interrupt can occur 
during the execution of another team. 

7. Final confirmation



   We verify this fact. Let processor
interrupt determines where in a
interrupted program. If it was interrupted
just after the command LD A, R, let the curb
for some time to yellow:


       ORG # 6000



       LD HL, # 8000

       LD (HL), # 81

       LD DE, # 8001

       LD BC, # 100

       LDIR

       LD A, # 80

       LD I, A

       IM 2



       EI


M1 CALL SUBR1

       JR M1


SUBR1 LD A, R
BP1 RET PE



       LD A, 4

       OUT (254), A

       LD HL, 0

       LD DE, 0

       LD BC, # 600

       LDIR; WAIT

       XOR A

       OUT (254), A

       RET



       ORG # 8181



       EXX

       EX AF, AF '



       POP HL

       PUSH HL

       LD DE, BP1

       SBC HL, DE

       JR NZ, NE_BP1



       LD A, 6

       OUT (254), A

       LD HL, 0

       LD DE, 0

       LD BC, # 600

       LDIR; WAIT


NE_BP1 EXX

       EX AF, AF '



       EI

       RET



   If incorrect operation command LD A, R
not connected with the fact that during its execution of the 
pulse interrupt, then we see how the top will border'a

flashes then green, then yellow. But
if the relationship between these two events there, then we 
should see how top border'a flashing yellow and the lower part 
- the green, and they should blink completely in sync.


   Run - and I see exactly what and
expected. Indeed, such a relationship
exist:



   But as can be related interruptions and
teamwork LD A, R? This team puts in a flag P / V content 
trigger interrupt IFF2. When interrupt enable this trigger is 
1, and when it comes to interrupt the momentum, it is 
automatically reset to 0 to eliminate reprocessing 
interruption. However, query processing interrupt begins during 
the last execution carried out by the bar team (Ie, commands LD 
A, R). And, apparently, already thrown trigger IFF2 copied to 
the flag P / V (indeed, in terms of CPU, interrupt at this 
point is already prohibited). 


   All of the above applies to the command LD
A, I. This information has been verified
on the original Z80 CPU ZILOG firm
and domestic counterparts KR1858VM1.


8. What does it lead and what to do?



   Application commands LD A, R and LD A, I for
determine the status of interrupt trigger,
generally used in many
programs (and even in the ROM TR-DOS). Here you
and an explanation of a number of strange lockups. It seems as 
if the probability of the pulse interrupt it at the time of the 
command LD A, R is small. But, first, the probability increases 
due to that this command can be executed in

program more than once (and for hovering
enough only incorrect execution), and secondly - if the program 
to This team met HALT, that is,

synchronization with interrupts, it may happen that the command 
LD A, R will always be executed at a time when most likely the 
next interrupt (or was BestView).




   Thus, this method is unreliable. But how do
be? It turns out that with 100% accuracy
determine the status of interrupt trigger
by the following simple rule:

 - Execute the command LD A, R;
 - If the flag P / V = ​​1 - means Interrupt
in fact authorized;
 - If the flag P / V = ​​0 - any interruption in
actually prohibited, or permitted,
but the team LD A, R incorrectly planted a flag.
To resolve this uncertainty, again
run the command LD A, R. If now
Flag P / V = ​​0 - hence, interrupts are prohibited (in fact, 
may not be so and run-time second-team LD

A, R has occurred - between the two
preemption is 1 / 50 seconds, and between the two teams LD A, R 
- much less time). If the flag P / V = ​​1 - mean

interrupts are enabled.


   Here's the relevant code fragment:

SUBR1 LD A, R

       JP PE, M1

       LD A, R
M1 PUSH AF

       DI



       ....



       POP AF

       DI

       RET PO

       EI

       RET



9. How do I use it?



   With a team of LD A, R is convenient to carry out testing of 
the processor to recognize the program under the emulator. Z80 
emulator executes instructions sequentially, one after another, 
and the team LD A, R will always be properly installed

Flag P / V. A real-Z80 is not.


   Here is a simple procedure for testing the processor, which 
returns the battery 1, if it is running on a real Z80, and 0 
otherwise. She tries to 65536 times read register R for 
interrupt enable, and if this even though least once a flag P / 
V set to 0 - it is concluded that the procedure works on 
Real-Z80. 

TESTZ80



       EI

       LD BC, 0
M1 LD A, R

       JP PO, QUIT

       INC BC

       LD A, B

       OR C

       JR NZ, M1

       RET
QUIT LD A, 1

       RET



   If recognized by the emulator, you can either
terminate the program (a kind of protection), or disable some
program segments that can be wrong
work under the emulator (for example, instead of
direct work with the use point VG93
Input # 3D13, etc.).

10. Correction STS 6.2



   In a debugger STS definition
status of trigger interrupt also occurs with the command LD A, 
R. Because of this, may not hold tracing program. When tracing 
STS runs each command (except for command transfer control) 
with the help of residents and after its implementation stores

the contents of processor registers and trigger status 
interrupts. That's where mistakes are possible. 


   Assume interrupts are enabled and traced a simple program:

# 8000 NOP
# 8001 JR # 8000



   Stopping the trace after a
time (if this option is disabled Indicate one minute is 
enough), we see that interrupts were prohibited. If

traced to a real program, such a ban could have an interrupt
impact on the entire course of its further implementation and 
even lead to a crash (if when tracing has got to command HALT).




   It is obvious that the STS should be
correction. Here's how
for version 6.2:


   You must first download and run the STS
file "sts6.2 ", which will be made and corrections.

   Then you need to find a free 14-byte
- Their function will be explained below. You can use the 
clipboard user function (With address # FE37). But in the 
version of the STS, I use this buffer is occupied by procedure 
of disassembling an assembly with labels ZX ASM, so I decided 
to cut Some text messages:


 'Block' -> 'Bl.' (Save 2 bytes)
 'Save' -> 'S.' (----/----- 2 --/--)
 'Load' -> 'L.' (----/----- 2 --/--)
 'DEFB' -> '' (----/----- 4 --/--)
 'FileName' -> 'Name' (----/----- 4 --/--)


   For this purpose, the address must be entered # EB24
the following sequence of bytes:


    # EB24: AE 46 72 6F ED 54 EF 46

    # EB2C: 69 6C E5 53 65 63 74 6F

    # EB34: F2 53 AE 4C AE 53 74 6F

    # EB3C: 70 20 69 E6 42 61 6E EB

    # EB44: 51 75 69 F4 54 72 61 63

    # EB4C: E5 53 74 61 72 44 69 F4

    # EB54: 73 61 73 ED A0 46 69 6C1

    # EB5C: E5 42 41 53 49 C3 20 44

    # EB64: 4F D3



   At # E702 changes the value of # 0A
at # 0E, to correctly print the name
File (FileName as string instead of just left Name).



   So now with the address # EB66 free 14
bytes. See where the STS is to determine the state trigger 
interrupts: 

# DFFE: LD (# 5BA1), SP

       LD SP, # 5BA1

       PUSH BC

       PUSH AF

       LD A, R

       DI

       LD BC, # 7FFD

       LD A, # 1F

       OUT (C), A

       LD B, # BF

       LD A, # 00

       OUT (C), A

       JP # E028



   Replace command LD A, R: DI on NOP, but
team JP # E028 - to JP # EB66. C address
# EB66 put this snippet:


     # EB66: LD A, R

            JP PO, # EB6E

            NOP

            JR # EB70

            LD A, R <

        > DI

            JP # E028



   Please note - this piece in any case, their work enhances
Register R by the same amount (7).
The fact is that more will be done yet
one team LD A, R, this time the desired
is to determine the value of the register R, and
correction will be made resulting
values, because R register value increases with each command, 
and need to know its value at the end of the implementation 
team traced. Here it looks like:


# DCA2: LD A, # 5A

       LD HL, # FEF4

       SLA (HL)

       RLA

       ADD A, (HL)

       RRCA

       LD (HL), A

       RET



   Constant # 5A at # DCA3 should
replaced by # 53, ie, reduced by 7 -
since the program was added an additional fragment, which 
increases the register R at 7, and must compensate for this 
change. 


   After that you only write
modified file to disk.




Other articles:

Aperativchik - On the control of the shell DEJA VU

Aperativchik - Number came late in the month.

Aperativchik - Freebies will be no more.

Topic - Provision # 2. Perspective.

Topic - On working with electronic drive in the IS-Dos.

Topic - A new crossroads - some of the complexities of the game The Castle.

Topic - the printer and the ZX-Spectrum (command system printer family Epson).

drop of solder - Ode to watch.

drop of solder - Scanner v1.3.

drop of solder - Disk protector v1.4 (scheme).

SOFTWARE - Overview of new products demos: Iris UltraDemo, Lazarus Trackmo, Russian Fields of Experiments, Pressure Trackmo.

SOFTWARE - Overview of new products games: White Eagle, Leprekon, Kozel, Puzzle (prerelease of Flash), Space, Translate Worlds, Devil-s Curse, Choppers: death match, Twilight: The Land of Shadows, Falen Angel, 12 Secret Book, The Cezar, Chainick horror in Flat.

SOFTWARE - Review sistemok: ASCII Convertor v2.71, Global Commander v1.31, BA v1.0, X-Copy.

SOFTWARE - Men like gods: the script for the game Elite III

SOFTWARE - The work of the program to print images XL-graph.

CODING - The Optimization - Building a table repetition of bytes.

CODING - Universal Player - Pro Tracker v3.31.

CODING - an undocumented feature of the processor Z80.

CODING - Conversion of graphics into text format ASCII.

CODING - How to create uncopyable whereas sector.

CODING - BUGS in Plaeyer-e Pro Tracker 3.x

ANOTHER WORLD - CPU Pentium III.

ANOTHER WORLD - At the crossroads of three worlds.

ANOTHER WORLD - News from the world of Amiga.

ANOTHER WORLD - My Choice - PC?.

Hall of Fame - What do we think about the scene.

Hall of Fame - Everyone on party!

Hall of Fame - On CD-ROM project from the city of Kemerovo.

Seven and 1 / 2 - April Fools' Day.

Seven and 1 / 2 - Purposely not think: seven stories from the seller to ZX software.

Seven and 1 / 2 - Anecdotes.

attempt at writing - Amiga rulez or suxx?

Advertising - Advertisements and announcements ...


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

Similar articles:
Feedback - contact the publisher.
Entry - the contents of rooms.
Through the Looking Glass - From the Chronicles of disappearances.

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