Programmers - Coding for beginners: “Immersion in movement.” Part two.

ZX Format #08
"Immersion in movement"    
         part two          
                               
music by COOPER                
(C)CREATOR product 1997        
________________________________
                               
  Ppubetctbyem everyone who decided to continue
live acquaintance with some subtleties
programming in machine code. And as soon as
You looked here, we will assume that
the first part was clear to you.           
                               
 Attention!  In the first part, in the program
there was a typo in plotting the point -
in the first line there was LD L,C, but it should
be LD L,B. Well, it's not that scary.
                               
 Well, let's continue the "immersion" :)        
 Let's continue to get acquainted with the methods of ycko-
reniya programs.                          
                               
 The frequently encountered task of resetting the re-
Hysteria A can be performed not only as
LD A,0, but also using the XOR A or
SUB A. They take up one byte less,
than LD A,0 and are executed at 3 clock cycles
yes, they really influenceflags.             
                               
 To reset HL, you can write SBC HL,HL,
but the result is affected by the carry flag.   
                               
 For subtraction without taking into account the carry flag
It's better to use addition. If you don't
you need to watch the flags, then feel free to do it
those are so.                                  
                               
 You can subtract HL from 20 like this:              
                               
   LD BC,20 ; 10 enter 20 in BC                              
   AND A ; 4 is needed to reset the carry flag, if there is one
              ; is set, then the extra unit will be subtracted       
   SBC HL,BC ; 15                                            
                               
   or you can do this:                                               
                               
   LD BC,0-20 ; 10 we enter the “reverse” number 20 into BC           
   ADD HL,BC ; 11                                            
                               
 The second example is much simpler and works
faster.  The operating principle is easy to understand
example with a mechanical watch:translate
you can move the time back 1 hour by turning the arrow
back an hour (usually you shouldn’t do this)
recommended), or you can scroll through the same
11 o'clock forward. True when
this method of subtraction is inconvenient to follow
behind the flags, but if this is not required -
feel free to use it.                    
                               
          Interrupts           
                               
 What is it and why is it needed? Recently
XL_DESIGN offered a game, music in combination
which slowed down her actions. When
the author was delicately pointed out this sample
lemma, he solved it simply - removed the music
ku...                                    
                               
 So, an interrupt is an external signal,
sent to the processor 50 times per second
(for masked interrupts). This is pro-
comes at those moments when video control
Lehr starts drawing another frame
images (just 50 times per second).   
 For a programmer, this means that from now on
At the start of each frame, the processor is offered
it is impossible to be distracted from performing the main task
program and go to the processing program
interruptions.  If interrupts are enabled -
he will do so, if not, he will offer
tion" will be ignored. Interrupts are divided
into 2 types: “masked” (those that can
be allowed or prohibited) and "hemacku-"negotiable" - are never ignored.
Speccy NMI (non masked interrupt) is used
It is used to operate the MAGIC button.    
                               
 How does an interrupt occur? Upon completion
the processor checks the current command - yes
Is there an interrupt signal and if so, how?
react (see above). Go to prog
The processing frame is carried out according to the principle
pu CALL. That is the processor remembers the current
The current PC value is on the stack and is passed along
set for this interrupt ad-
res.  The address depends on the processing mode.
There are several modes (interrupt mask): 
                               
 IM 0 - we won't even talk about it,
since this mode requires a controller
interruptions, which are not found in any
Spectrum, and without a controller it is completely
equivalent to IM 1 (on a stable machine).
IM 1 - processed at address 56 (#38)
IM 2 - mode allows you to set your own ad-
res for the processing procedure.             
                               
 NMI (non-maskable interrupt) - processing
is determined by the procedureaddress 102 (#66).
When you press the magic button, the
switching ROM to TR-Dos ROM (or in those
heboe ROM), where his program sits
processing. By the way, it can also be replaced
on your own, but already through nepenporpammupoba-
tion of ROM.                                 
                               
 Now in more detail. As soon as you turn on
read the computer and a screen will appear in front of you
button, IM 1 mode will be turned on, which
used mainly for polling
viatures.  This mode is of particular value to us.
does not represent any significance, because processes-
only by ROM procedures. Therefore we will
talk about IM 2 mode. For control
interrupt processing modes exist
the following commands:                       
                               
 IM 0, IM 1, IM 2                       
 DI  (Disable interrupt) - to disable
masked interrupts.                
 EI  (Enable interupt)  - for resolution
masked interrupts.                
                               
 When interrupts are disabled, the processor will
they will not respond. Unmasked
interrupts are not disabled.In order to track the status of the interruption
However, you can use the following procedure:
procedure:                                  
                               
   LD A,I ; read interrupt status                    
                ; to parity/overflow flag               
  JP PE,EI_INT ; jump if interrupts are enabled           
DI_INT ... ; interrupts are disabled                        
EI_INT ...                                                    
                               
 Now we know how to enable interrupts
and we can discuss how to install your
addresses for the interrupt handler. (in re-
press IM 2)                               
 The processor has a special register
for this, this is register I - the interrupt vector
vaniya. It indicates the most significant byte of the ad-
res containing the address of the handler.
The low byte is read from the data bus and to
normal machine is always equal to 255 or
#FF.  But due to the fact that abnormal ma-
quite a lot of tires (glitchy pentagons)
you have to make allowances for them. Glitch-
their beauty is that wheninterruption processing
the devil can be read from their bus
knows what.  In this regard, it is necessary
build a table 256 bytes long.        
                               
 Next we will give an example of a “builder”
such a sign. After construction it will be
occupy 512 bytes after the TABLE address.
Interrupts will be enabled, that is,
by the time of construction the botchik should already
be in the right place in memory.        
                               
TABLE EQU #FCOO ; jump table address of 257 bytes,
; and the low byte of the address must be zero.     
; #FCOO is the highest address possible for this procedure.    
                               
INT EQU #8000 ; address of the interrupt handler, put here -
                  ; the value you need.                   
IM2_MAKE                                                     
        DI                                                   
        LD HL,TABLE                                           
        LD A,H                                               
        INC A                                                 
MAKE    LD (HL),A                                             
        INC L                                                 
        JR NZ,MAKE                                            
        INC H                                                 
        LD (HL),A                                             
        DEC A                                                 
        LD I,A                                                
        IM 2                                                  
        LD HL,TABLE                                           
        INC H                                                 
        LD L,H                                                
        LD (HL),#C3                                           
        INC HL                                                
        LD DE,INT                                             
        LD (HL),E                                             
        INC HL                                                
        LD (HL),D                                             
        EI                                                    
        RET                                                   
                               
Обработчик прерываний следует делать так:
                               
INT                                                           
        DI  PUSH AF,BC,DE,HL,IX,IY                                
        EXX                                                   
        EX AF,AF                                              
        PUSH AF,BC,DE,HL                                      
        ...                                                   
        собственные процедуры                                 
        ...                                                   
        POP HL,DE,BC,AF                                       
        EX AF,AF                                              
        EXX                                                   
        POP IY,IX,HL,DE,BC,AF                                 
        EI  RET                                                   
                               
 It is advisable to disable interrupts because
there are poorly tuned Spectrums, which
a long interruption may still have time to arrive
times before exiting the handler.            
                               
 We should also not forget that interrupting
it’s not rubber, on average it’s 64-68 thousand
a thousand bars. If your procedures are not successful -
are expected to complete within this time, then execute
The program will slow down by half
(including interrupts).  Since the most
brake machine we have Scorpio and these
there are a lot of scorpions, you need to avoid them
situations and adhere to the barrier in
65 thousand cycles. In general, this topic is under-
Illuminated in detail in ZF-3.                 
                               
 Basically, interrupt is used for
playing music on AY, drawing chickens
sorting and counting time. For music you need
just don’t disable interruptions in the program
meh and she will never slow down.
                               
 Almost all music editors
compile music together with the player, it,
Of course, you don’t have to add it, but it’s
you won't need it yet. The player is working
everywhere the same. First it must be removed
tally and then lose with frequentthat 50 Hz, that is, once per interruption.
This is done using your handler
very simple. The interrupt calls
player and that's it! For example like this:              
                               
        CALL INSTALL                                         
        ...                                                   
INT                                                           
        DI                                                   
        PUSH AF,BC,DE,HL,IX,IY                               
        EXX                                                   
        EX AF,AF                                             
 PUSH AF,BC,DE,HL                                     
                               
        CALL PLAY                                             
                               
        POP HL,DE,BC,AF                                      
        EX AF,AF                                             
        EXX                                                   
        POP IY,IX,HL,DE,BC,AF                                 
        EI                                                   
        RET                                                   
                               
 The INSTALL and PLAY addresses will be given to you by the music
cal editor for music compilation.  
                               
 Well, it seems about masked interruptions-
nia everything. Now a few words about hemackupobah-
nal interruptions. They have a larger npuo-
putet than maskable ones, that is, the processor
considers them more important. Using the program
pammatopa you can set the address yourself
NMI handler (non-maskable interrupt)
nia) by replacing the code in address 102 or
#66 in Tr-dos ROM. For example, this is how it is done
shadow service monitor on Scorpion. He-
which craftsmen flash into STS ROM, these are
will be better than Scorpio service-mo-
hutopa.Forwarding data blocks.    
                               
 A very common task. The process
Sora Z80 there are several similar commands. 
                               
For example, LDIR forwards bytes from the address
ca contained in the HL register to the address,
contained in the DE register. Quantity
The transmitted bytes are entered into the BC register.
Transferring one byte takes 21 clock cycles.
An analogue of this command looks like this:        
                               
        LD HL,SOURCE ; 10                                
        LD DE,DESTINATION ; 10                                
        LD BC,BYTES ; 10                                
LOOP LD A,(HL) ; 7                                 
 LD (DE),A ; 7                                 
        INC HL ; b                                 
        INC DE ; bDEC BC ; b                                 
        LD A,B ; 4                                 
        OR C ; 4                                 
        JR NZ,LOOP ; 12/7                              
                               
 You can compare 53 clock cycles per byte with this
loop and 21 using LDIR.             
                               
 The LDDR command does the same thing, but
ki move from the end.                 
                               
 The LDI command is almost LDIR, but it is not
cyclic, it sends one byte from
HL to DE, adds one to HL and DE,
decreases BC by one, and if BC is equal
zero, sets the overflow flag
nia/parity. Transferring a byte takes 16
beats  The LDD command does the same,
but subtracts one from HL and DE.       
                               
 It is possible to construct an analogue of LDIR with
using LDI:                             
                               
        LD HL,SOURCE ; 10                                
        LDDE,DESTINATION ; 10                                
        LD BC,BYTES ; 10                                
LOOP LDI ; 1b                                
        JP PE,LOOP ; 10                                
                               
 You can use LDI instead of LDIR if
we need to spend our machine money a little more economically
time. For example:                         
 We put LDI on each byte sent.
There is one drawback - shipping costs are
This block will require a lot of memory -
tee.                                      
 There is another way: loop several
LDI commands. Here the problem arises - when
The quality of bytes sent must be
is a multiple of the number of LDI commands, that is,
if we divide the number of bytes by the number
LDI quality, then it must be divided without special
tatka. For example:                         
                               
        LD HL,SOURCE ; 10                                
        LD DE,DESTINATION ; 10                                
        LD BC,BYTES ; 10                                
LOOP LDI ; 1b                                
        LDI ; 1b                                
        LDI ; 1b                                
        LDI ; 1b                                
        JP PE,LOOP ; 10                                
                               
 This cycle can send blocks,
multiples of 4, for example 4,8,16,32...1024 bytes
ta.  A byte is sent in 18 clock cycles. This
slower than many consecutive LDIs,
but faster than LDIR.                    
                               
 So, with processor commands we know
we've been making fun, now let's move on to the "cunning" ways
data transfer dogs.                  
                               
 The fastest way (and the most special) can be
may be useful only in rare situations
yah.                                      
                               
        LD SP,END_DESTINATION ;indicates the end of the region, in 
                               ;which needs to transfer data 
        LD HL,#0000;10 ;the data is directly indicated in 
                        ;register HL                          
        PUSH HL ;11                                           
        ...                                                   
                               
 Sending one byte takes 10.5
beats! This is the fastest transfer method
data.  This is passing data through the stack,
for its proper operation it is necessary to
first remember the stack pointer, and then
how the procedure works, bocctaho-
twist it.                                
                               
For example:                                
                               
        LD (STACK+1),SP                                       
 LD SP,END_DESTINATION+2                               
DATAS LD HL,#0000                                           
        PUSH HL                                               
        LD HL,#0000                                           
        PUSH HL                                               
        ...                                                   
STACK LD SP,0                                               
                               
 The most important thing when using a stack is
these are interruptions. If this procedure works
melts into interruption, then nothing special
nothing terrible will happen, but if there is an interruption
will come while this procedure is running,
the data on the stack will be corrupted. They, co-
Of course, they will rub in the necessary ones during the next one
transmission, but if it happens at the end
forwarding, then “garbage” on the guarantee screen
pobah. Therefore, interrupts need to be disabled
before storing the stack and allowing (es-
whether necessary) after restoring the stack.     
 Let me remind you that this method is very specific.
cue, in order to be able to transfer
to create data, they must first be placed in
HL registers.  For example, you can remember
address of the byte following the DATAS label
(that is, DATAS+1), is located right there
there arethe two bytes we need. You can go there
register your data, and for each trace
add the next two bytes to the address of four
re by type:                              
                               
        LD DE,DATAS+1 ; data address in forwarding block        
        LD HL,DATA ; the address containing the data that 
                      ; need to be forwarded                       
        LD BC,NUM*2 ; how many _words_ do we need to convey? 
; the number must be _no_more_than_commands LD HL,#0000 in_block     
; forwarding. For this procedure, we also multiply BC by 2.       
LOOP                                                         
        LDI                                                   
        LDI                                                   
        INC HL                                               
        INC HL                                               
        JP PE,LOOP  Forwarding through registers using
I eat a stack.                                
                               
 The procedure itself looks like this:            
                               
        LD SP,SOURCE                                         
        POP AF,BC,DE,HL                                       
        EXX                                                   
        POP BC,DE,HL                                         
        LD SP,DESTINATION                                     
        PUSH HL,DE,BC                                         
        EXX                                                   
        PUSH HL,DE,BC,AF                                     
                               
 I think you already understand everything here, pop
try to figure it out yourself, you’ll understand
It will only benefit you.          
_______________________________

Share your thoughts about the article