• Keine Ergebnisse gefunden

Block Move and Block Compare Instructions

Im Dokument Assembly Language Subroutines (Seite 48-52)

Another way to simplify array processing is to use the Z80's block move and block compare instructions. The block move instructions not only transfer data from one memory location to another without using the accumulator, but they also update the array pointers and decrement a 16-bit loop counter. Thus, a block move instruction can replace a sequence of load, increment, and decrement instructions. Repeated block move instructions continue transferring data, updating the pointers, and decre-menting the counter until the counter is decremented to zero. Block compare instruc-tions are similar to block moves, except that only a single pointer is involved (the other operand is in the accumulator), and the repeated versions also terminate if the operands being compared are equal (this is referred to as a true comparison).

A further convenience of block moves and block compares is that they solve the problem of testing a 16-bit counter for O. Both block moves and block compares clear

36

Z80 ASSEMBLY LANGUAGE SUBROUTINES

the Parity/Overflow flag if the 16-bit counter (always in register pair BC) is decre-mented to zero, and set the Parity/Overflow flag otherwise. Note that the indicator is the Parity/Overflow flag, not the Zero flag.

The block move and compare instructions are the following:

· LDI (LDD) moves a byte of data from the address in HL to the address in DE, decrements BC, and increments (decrements) DE and HL.

· LDIR (LDDR) repeats LDI (LDD) until BC is decremented to

o.

· CPI (CPD) compares the accumulator to the data at the address in HL, decre-ments BC, and incredecre-ments (decredecre-ments) HL. Both CPI and CPD set the Zero flag if the operands being compared are equal, and clear the Zero flag otherwise.

· CPIR (CPDR) repeats CPI (CPD) until BC is decremented to O.

Note that block moves reserve BC, DE, and HL for special purposes, while block compares reserve only BC and HL.

Examples

~INITIALIZE SOURCE POINTER

~INITIALIZE DESTINATION POINTER

~MOVE A BYTE OF DATA

Obviously, the overhead of loading all the register pairs makes it uneconomical to use LDI or LDD to move a single byte of data.

2. Move two bytes of data from memory locations ADDRI and ADDRI+ I to memory locations ADDR2 and ADDR2+ 1.

or

; INITIALIZE SOURCE POINTER

;INITIALIZE DESTINATION POINTER

;MOVE TWO BYTES OF DATA

;NUMBER OF BYTES TO MOVE

=

2

; INITIALIZE SOURCE POINTER

; INITIALIZE DESTINATION POINTER

;MOVE TWO BYTES OF DATA

The block move instructions become more useful as the number of bytes to be moved increases.

CHAPTER 1. GENERAL PROGRAMMING METHODS

37

3. Move ten bytes of data from memory locations starting at ADDRI to memory locations starting at ADDR2.

or

;INITIALIZE SOURCE POINTER

; INITIALIZE DESTINATION POINTER

;MOVE TEN BYTES OF DATA

;NUMBER OF BYTES TO MOVE = 10

;INITIALIZE SOURCE POINTER ,INITIALIZE DESTINATION POINTER

;MOVE TEN BYTES OF DATA

4. Examine memory locations starting at ADDR until one is encountered that contains 0 or until 256 bytes have been examined.

LD The final value of the Zero flag indicates why the program exited.

Zero flag = 1 if the program found a 0 in memory.

Zero flag = 0 if the program decremented BC to O.

The block move and block compare instructions are convenient, but their forms are restricted and their applications are limited. The programmer must remember the following:

. BC always serves as the counter; it is decremented after each iteration. The Parity / Overflow flag (not the Zero flag) indicates whether BC has been decremented to O. Be careful-the P / V flag is set to 0 ifBC has been decremented toO; the polarity is opposite of that used with the Zero flag. Thus, after a block move or block compare, the relevant conditional branches have the following meanings:

lP PE means "branch if BC has not been decremented to 0."

lP PO means "branch if BC has been decremented to 0."

HL always serves as the source pointer in block moves and as the memory pointer in block compares. HL is incremented or decremented after the data is transferred or a comparison is performed.

. DE always serves as the destination pointer in block moves; it is not used in block compares. Like HL, DE is incremented or decremented after the data is transferred.

Note also that LDI and LDIR increment both HL and DE, while LDD and LDDR decrement both pairs.

38

Z80 ASSEMBLY LANGUAGE SUBROUTINES

• Repeated block comparisons exit if either a true comparison occurs or Be is decremented to O. Testing the Zero flag will determine which condition caused the exit.

TABLE LOOKUP

Although the Z80 processor has indexing, the calculations required for table lookup must be performed explicitly using the ADD HL or ADD xy instruction. This is because the Z80's indexing assumes a variable 16-bit address in an index register and a fixed 8-bit offset. As with array manipulation, table lookup is simple if the table consists of 8-bit data items; it is more complicated if the table contains longer items or addresses. The instructions EX DE,HL and lP (HL) or lP (xy) can be useful, but require the programmer to place the results in specific 16-bit registers.

Examples

1. Load the accumuiator with an element from a table. Assume that the base address of the table is BASE (a constant) and the 16-bit index is in memory locations INDEX and INDEX+I (MSB in INDEX+1).

LD DE. BASE LD HL. (INDEX) ADD HL.DE LD A. (HU

;OET BASE ADDRESS

;OET INDEX

;CALCULATE ADDRESS OF ELEMENT

;OBTAIN THE ELEMENT

Reversing the roles of DE and HL would slow down the program since LD DE,(ADDR) executes more slowly and occupies more memory than does LD HL,(ADDR). This asymmetry is caused by the fact that only LD HL,(ADDR) is an original 8080 instruction; the direct loads of other register pairs (including the stack pointer) are additions to the underlying 8080 instruction set.

2. Load the accumulator with an element from a table. Assume that the base address of the table is BASE (a constant) and the index is in the accumulator.

LD L.A LD H.O LD DE. BASE ADD HL.DE LD A. (HU

;EXTEND INDEX TO 16 BITS IN HL

;OET BASE ADDRESS

;CALCULATE ADDRESS OF ELEMENT

;OBTAIN THE ELEMENT

3. Load register pair DE with a 16-bit element from a table. Assume that the base address of the table is BASE (a constant) and the index is in the accumulator.

ADD A.A ;DOUBLE INDEX FOR 16-BIT ELEMENTS LD L,A ;EXTEND INDEX TO 16 BITS

LD H,O

LD BC,BASE ADD HL,BC LD E, (HU

INC HL LD D, (HU

CHAPTER 1 GENERAL PROGRAMMING METHODS

39

;GET BASE ADDRESS

;CALCULATE STARTING ADDRESS

;GET LSB OF ELEMENT

;GET MSB OF ELEMENT

You can also use the instruction ADD HL,HL to double the index; it is slower than ADD A,A but it automatically handles cases in which the doubled index is too large for 8 bits.

4. Transfer control Uump) to a 16-bit address obtained from a table. Assume that the base address ofthe table is BASE (a constant) and the index is in the accumulator.

ADD A, A ; DOUBLE INDEX FOR 16-BIT ELEMENTS

;CALCULATE STARTING ADDRESS

;GET LSB OF DESTINATION

;GET MSB OF DESTINATION

; ,JUMP TO DESTI NAT I ON

The common uses of jump tables are to implement CASE statements (multi-way branches used in languages such as FORTRAN, Pascal, and PLjI), to decode com-mands from a keyboard, and to respond to function keys on a terminal.

Im Dokument Assembly Language Subroutines (Seite 48-52)