• Keine Ergebnisse gefunden

CONFUSING ADDRESSES AND DATA

Im Dokument Assembly Language Subroutines (Seite 161-164)

The rules to remember are

· LD requires an address when you want to move data to or from memory. That address must be placed in parentheses.

· The standard assembler treats all operands as data unless they are enclosed in parentheses. Thus, if you omit the parentheses around an address, the assembler will treat it as a data item.

• DJNZ, JP, JR, and CALL always require addresses.

There is some confusion with addressing terminology in jump instructions. These instructions essentially treat their operands as if one level of indirection had been removed. For example, we say that JP 2040H uses direct addressing, yet we do not place the address in parentheses. Furthermore, JP 2040H loads 204016 into the program counter, much as LD HL,2040H loads 204016 into register pair HL. LD HL,(2040H) loads the contents of memory locations 204016 and 204116 into register pair HL. Note also that JP (HL) loads HL into the program counter; it does not use HL indirectly or access the memory at all.

Examples

1. LD A,40H loads the number 4016 into the accumulator. LD A,(40H) loads the contents of memory location 004016 into the accumulator.

2. LD HL,OCOOH loads OC0016 into register pair HL (OCI6 into Hand 0016 into L).

LD HL,(OCOOH) loads the contents of memory locations OC0016 and OCOl16 into register pair HL (the contents of OCOO16 into L and the contents of OCOl16 into H).

3. JP (xy) transfers control to the address in an index register. No indexing is performed, nor is the address used to access memory.

Confusing addresses and their contents is a common error in handling data struc-tures. For example, the queue of tasks to be executed by a piece of test equipment might consist of a block of information for each task. That block might contain

Starting address of the test routine

Number of seconds for which the test is to run

CHAPTER 3 COMMON PROGRAMMING ERRORS

149

Address in which the result is to be saved

Upper and lower thresholds against which the result is to be compared Base address of the next block in the queue.

Thus, the block contains data, direct addresses, and indirect addresses. Typical errors that a programmer could make are

· Transferring control to the memory locations containing the starting address of the test routine, rather than to the actual starting address.

Storing the result in the block rather than in the address specified in the block.

Using a threshold as an address rather than as data.

Assuming that the next block starts in the current block, rather than at the base address given in the current block.

Jump tables are another common source of errors. The following are alternative implementations:

· Form a table of jump instructions and transfer control to the correct element (for example, to the third jump instruction).

· Form a table of destination addresses and transfer control to the contents of the correct element (for example, to the address in the third element).

You will surely have problems if the processor uses jump instructions as addresses or VIce versa.

FORMAT ERRORS

The rules you should remember for the standard Z80 assembler are

· An H at the end of a number indicates hexadecimal and a B indicates binary.

· The default mode for numbers is decimal; that is, the assembler assumes all numbers to be decimal unless they are specifically marked otherwise.

· All operands are treated as data unless they are enclosed in parentheses. Operands enclosed in parentheses are assumed to be memory addresses.

· A hexadecimal number that starts with a letter digit (A, B, C, D, E, or F) must be preceded by 0 (for example, OCFH instead of CFH) for the assembler to interpret it correctly. Of course, the leading 0 does not affect the value of the number.

· All arithmetic and logical operations are binary, except DAA, which corrects the result of an 8-bit binary addition or subtraction to the proper BCD value.

150

Z80 ASSEMBLY LANGUAGE SUBROUTINES

You should beware of the following common errors:

• Omitting the H from a hexadecimal operand. The assembler will assume it to be decimal if it contains no letter digits and to be a name if it starts with a letter. The assembler will indicate an error only if it cannot interpret the operand as either a decimal number or a name.

· Omitting the B from a binary operand. The assembler will assume it to be decimal.

· Confusing decimal (BCD) representations with binary representations. Remem-ber, ten is not an integral power of two, so the binary and BCD representations are not the same beyond nine. BCD constants must be designated as hexadecimal numbers, not as decimal numbers.

· Confusing binary or decimal representations with ASCII representations. An ASCII input device produces ASCII characters and an ASCII output device responds to ASCII characters.

Examples

1. LD A,(2000)

This instruction loads the accumulator from memory address 200010 (070016), not address 200016. The assembler will not produce an error message, since 2000 is a valid decimal number.

2. AND 00000011

This instruction logically ANDs the accumulator with the decimal number 11 (10112), not with the binary number 11 (310). The assembler will not produce an error message, since 00000011 is a valid decimal number despite its unusual form.

3. ADD A,40

This instruction adds the number 4010 to the accumulator. Note that 4010 is not the same as BCD 40, which is 4016; 4010 = 2816. The assembler will not produce an error message, since 40 is a valid decimal number.

4. LD A,3

This instruction loads the accumulator with the number 3. If this value is now sent to an ASCII output device, the device will respond as if it had received the character ETX (0316), not the character 3 (3316). The correct version is

LD ;OET AN ASCII 3

CHAPTER 3 COMMON PROGRAMMING ERRORS

151

If memory location 204016 contains a single digit, the sequence LD A, (2040H)

OUT c.DEVCE), A

will not print that digit on an ASCII output device. The correct sequence is LD A, (2040H) ;GET DECIMAL DIGIT

ADD A, ~O·' ; AD,JUST TO ASCI I OUT <DEVCE), A

If input port INDEV contains a single ASCII decimal digit, the sequence IN A, <INDEV)

LD (2040H),A

will not store the actual digit in memory location 204016. Instead, it will store the ASCII version, which is the actual digit plus 3016. The correct sequence is

IN A, <INDEV.I SUB ·'0'

LD (2040H.I, A

;GET ASCII DIGIT

;AD,JUST TO DECIMAL

Performing decimal arithmetic on the Z80 is awkward, since a DAA instruction is required after each 8-bit addition or subtraction. Chapter 6 contains programs for decimal arithmetic operations. Since DAA does not work properly after DEC or INC, the following sequences are necessary to perform decimal increment and decrement by 1:

or

Add 1 to the accumulator in decimal.

ADD A,1 DAA

Subtract 1 from the accumulator in decimal.

SUB 1

DAA

ADD A,99H DAA

In the second alternative, Carry is an inverted borrow.

Im Dokument Assembly Language Subroutines (Seite 161-164)