home *** CD-ROM | disk | FTP | other *** search
- CHAPTER 5 SOME EXCLUSIVE FEATURES OF A86
-
-
- The IF Statement
-
- As a "nudge" in the direction of structured programming, A86
- offers the IF statement. Suppose you want to conditionally skip
- around just one instruction. Ordinarily, this would require, for
- example:
-
- JNZ >L1 ; skip the following move if NZ
- MOV AX,BX ; make this move only if Z
- L1: ; this label exists only for the above skip
-
- You may replace the above code with the single line:
-
- IF Z MOV AX,BX
-
- The above line generates exactly the same code as the previous 3
- lines-- a conditional jump of the opposite condition, around the
- statement given in the tail of the IF statement. The statement
- can be a macro call, giving you the opportunity to skip something
- more complicated.
-
- You may use any condition that would follow the "J" in a
- conditional jump instruction, except CXZ, which does not have a
- reverse condition. The assembler interprets the condition by
- appending a "J" to the beginning of the condition; so that the
- symbols "C", "NC", "Z", "NZ", etc. are not reserved by the
- assembler, and can be defined in other contexts.
-
-
- Multiple operands to PUSH, POP, INC, DEC
-
- A86 will accept any number of register operands for the
- instructions PUSH, POP, INC, and DEC; it will generate the
- appropriate machine instruction for each operand. For example,
- the statement PUSH AX,BX is the same as the two statements PUSH
- AX and PUSH BX.
-
- A numeric operand appearing in an INC or DEC statement will cause
- the previous INC(s) or DEC(s) to be propagated that number of
- times. For example, the statement INC AX,4 will generate 4 INC
- AX instructions. The statement DEC AL,BX,2 will generate DEC AL,
- DEC BX, DEC AL, DEC BX. Sorry, numeric operands are not allowed
- if any of the operands affected was a forward reference or
- relocatable quantity; e.g., INC FOO,2 where FOO is undefined. In
- most such cases, you'll want to code the more efficient ADD FOO,2
- anyway.
- 5-2
-
- Conditional Return Instructions
-
- Programmers accustomed to the conditional return instructions of
- the 8080/Z80 will appreciate the following feature: A86 allows
- the operand to a conditional jump instruction to be one of the
- three RET instructions RET, RETF, or IRET. The assembler will
- find a nearby return instruction of the indicated flavor, and use
- that as the target for the conditional jump. For example, JZ RET
- is the replacement for the 8080's RZ return-if-zero instruction.
- In other 8086 assembly languages, you have to find the nearby
- instruction yourself, attach a label to it, and use that label.
- Note that it does not suffice to attach a label to a single RET
- instruction and use that label throughout the program: the range
- of conditional jumps is only 128 bytes in either direction.
-
- What happens if A86 does not find a nearby return instruction? In
- that case, A86 issues an error, "02 Jump > 128", for the next
- matching return instruction in the program. If there is no
- subsequent return instruction, the return mnemonic will appear as
- an undefined symbol at the end of the program. In either case,
- you correct the problem by inserting a free-standing return
- instruction at some nearby point in the program, where it will
- not affect the existing code (typically following an
- unconditional JMP instruction). If there is no good place to
- insert a return instruction, you can always replace the "Jcond
- RET" with an "IF cond RET".
-
-
- A86 extensions to the MOV instruction
-
- There are a number of MOV instructions available in A86 that are
- not a part of the machine instruction set.
-
- First, moves between segment registers, and of immediate
- constants into segment registers are allowed. For example, if
- you code MOV ES,DS , the assembler will generate a PUSH DS
- followed by a POP ES; which will effect the move that you
- intended. If you code MOV DS,0 , the assembler will generate
- PUSH AX; MOV AX,0; MOV DS,AX; POP AX. This is mainly a
- convenience for D86 users to load segment registers manually.
-
- Second, MOV allows 3 operands. A statement MOV x,y,z is
- equivalent to the two statements MOV y,z followed by MOV x,y.
- Sorry, but segment overrides are not allowed in conjunction with
- 3-operand MOVs. The override preceding the MOV is ambiguous in
- its meaning; and overrides within operands cannot be handled
- correctly by A86. You'll have to code two MOV instructions if
- you want either or both to have a segment override.
- 5-3
-
- Local Labels
-
- If you examine most assembly language program symbol tables, you
- will find that the symbols can be partitioned into two levels of
- significance. About half the symbols are the names of
- procedures and variables having global significance. If the
- names of these symbols are chosen intelligently and carefully,
- the program's readability improves drastically. (They usually
- aren't chosen well, most often because the assembler restricts
- symbols to 6 letters, or because the programmer's habits are
- influenced by such assemblers.)
-
- The other half of the symbols in a program have a much lower,
- local significance. They are only place markers used to
- implement small loops and local branching (e.g., "skip the next 2
- instructions if the Z-flag is set"). Assigning full-blown names
- to these labels reduces the readability of your program in two
- ways: First, it is harder to recognize local jumps for what they
- are-- they are usually the assembly language equivalent of high
- level language constructs like IF statements and WHILE loops.
-
- Second, it is harder to follow the global, significant symbols
- because they are buried in a sea of the place marker symbols in
- the symbol table.
-
- A86 solves this problem with local symbols. If a symbol in your
- program consists of a single letter followed by one or more
- decimal digits (L3, X123, Y37, etc.), then the symbol is a local
- symbol. Local symbols do not appear in the A86 XREF
- cross-reference listing. They can also be redefined to something
- completely different later in the program.
-
- Because local labels can be redefined, you must take care to
- specify which one you are referring to in your program. If your
- reference is a forward reference (the label occurs further down
- in the program from the reference), then the reference must be
- preceded by a ">". For example,
-
- L2:
- MOVSB
- INC BX
- LOOP L2 ; lack of ">" means L2 is above this statement
- .
- .
- JNZ >L2 ; ">" indicates L2 is below this statement
- .
- .
- L2:
-
- I recommend that you assign all your local labels the names L0
- through L9. If your program is so complex that it needs more
- than 10 place holders in any one stretch of code, then that
- stretch needs to be rewritten.
- 5-4
-
- Operands to AAM and AAD Instructions
-
- Those of you who have examined 86 family opcodes with an eagle
- eye will have noticed a somewhat spurious "0A" opcode generated
- after every AAM or AAD instruction. The opcode is there to
- provide the constant divisor or multiplicand for the instruction.
- Believe it or not, there wasn't enough room in the microcode of
- the original 8086 to hold this constant! Although Intel has
- never announced the generality of AAM and AAD, it is there: you
- can substitute any other constant for 0A (decimal 10), and that
- constant will be used. A86 supports this by letting you give a
- constant byte-sized operand to AAM or AAD. Particularly useful
- are the instructions AAM 16, which unpacks AL into nibbles AH and
- AL; and AAD 16, which reverses the process, packing nibbles AH
- and AL into AL.
-
- WARNING: A couple of my users point out to me that the AAD
- instruction with a general operand won't work on the NEC V20 and
- V30 chips. The operand is assumed to be 10 no matter what it
- really is. Since a large number of PC "speed up" kits involve
- switching to NEC chips, this will be seen on many PC's. You
- should not use AAD with an operand if you want your program to
- run on everybody's machine. Too bad. AAM works fine, though.
-
-
- Single-Operand Forms of the TEST Instruction
-
- A86 allows the TEST instruction to have a single operand, to set
- the flags according to the value of the operand. If the operand
- is a register, A86 generates a TEST of the register with itself.
- If the operand is a memory quantity, A86 generates a TEST of the
- memory with the constant -1 (i.e., the quantity will be ANDed
- with an all 1's constant). For example, instead of TEST DL,DL,
- you can code simply TEST DL. Instead of TEST WVAR,0FFFF, you can
- code simply TEST WVAR.
-
-