home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / A86V402.ZIP / A09.DOC < prev    next >
Text File  |  1994-12-21  |  26KB  |  608 lines

  1. CHAPTER 9   DIRECTIVES IN A86
  2.  
  3.  
  4. Segments in A86
  5.  
  6. The following discussion applies when A86 is assembling a .COM
  7. See the next chapter for the discussion of segmentation for .OBJ
  8. files.
  9.  
  10. A86 views the 86 computer's memory space as having two parts: The
  11. first part is the program, whose contents are the object bytes
  12. generated by A86 during its assembly of the source.   A86 calls
  13. this area the CODE SEGMENT.  The second part is the data area,
  14. whose contents are generated by the program after it starts
  15. running.  A86 calls this area the DATA SEGMENT.
  16.  
  17. Please note well that the only difference between the CODE and
  18. DATA segments is whether the contents are generated by the
  19. program or the assembler.  The names CODE and DATA suggest that
  20. program code is placed in the CODE segment, and data structures
  21. go in the DATA segment.  This is mostly true, but there are
  22. exceptions.  For example, there are many data structures whose
  23. contents are determined by the assembler: pointer tables, arrays
  24. of pre-defined constants, etc.  These tables are assembled in the
  25. CODE segment.
  26.  
  27. In general, you will want to begin your program with the
  28. directive DATA SEGMENT, followed by all your program variables
  29. and uninitialized data structures, using the directives DB, DW,
  30. and STRUC.  If you do not give an ORG directive, A86 will begin
  31. the allocation immediately following the end of the .COM program.
  32. You can end the DATA SEGMENT allocation lines with the DATA ENDS
  33. directive, followed by the program code itself.  A short program
  34. illustrating this suggested usage follows:
  35.  
  36. DATA SEGMENT
  37.   ANSWER_BYTE  DB ?
  38.   CALL_COUNT   DW ?
  39.  
  40. CODE SEGMENT
  41.   JMP MAIN
  42.  
  43. TRAN_TABLE:
  44.   DB 16,3,56,23,0,9,12,7
  45.  
  46. MAIN:
  47.   MOV BX,TRAN_TABLE
  48.   XLATB
  49.   MOV ANSWER_BYTE,AL
  50.   INC CALL_COUNT
  51.   RET
  52.  
  53. A86 allows you to intersperse CODE SEGMENTs and DATA SEGMENTs
  54. throughout your program; but in general it is best to put all
  55. your DATA SEGMENT declarations at the top of your program, to
  56. avoid problems with forward referencing.
  57.                                                               9-2
  58.  
  59. CODE ENDS and DATA ENDS Statements
  60.  
  61. For compatibility with Intel/IBM assemblers, A86 provides the
  62. CODE ENDS and DATA ENDS statements.  The CODE ENDS statement is
  63. ignored; we assume that you have not nested a CODE segment inside
  64. a DATA segment.  The DATA ENDS statement is equivalent to a CODE
  65. SEGMENT statement.
  66.  
  67.  
  68.  
  69. The ORG Directive
  70.  
  71. Syntax:  ORG address
  72.  
  73. ORG moves the output pointer (the location counter at which
  74. assembly is currently taking place within the current segment) to
  75. the value of the operand.  In the CODE segment, the operand
  76. should be an absolute constant, or an expression evaluating to an
  77. absolute, non-forward-referenced constant.  In the DATA segment,
  78. the operand may be a forward reference or an expression
  79. containing one or more forward references.  All symbols in the
  80. segment will be resolved when the forward references to the ORG
  81. operand are all resolved.
  82.  
  83. There is a special side effect to ORG when it is used in the CODE
  84. segment.  If you begin your code segment with ORG 0, then A86
  85. knows that you are not assembling a .COM program; but are instead
  86. assembling a code segment to be used in some other context
  87. (examples: programming a ROM, or assembling a procedure for older
  88. versions of Turbo Pascal).  The output file will start at 0, not
  89. 0100 as in a .COM file; and the default extension for the output
  90. file will be .BIN, not .COM.  However, if you later issue an ORG
  91. 0100 directive, the default will revert back to .COM.
  92.  
  93. Other than in the above example, you should not in general issue
  94. an ORG within the CODE segment that would lower the value of the
  95. output pointer.  This is because you thereby put yourself in
  96. danger of losing part of your assembled program.  If you
  97. re-assemble over space you have already assembled, you will
  98. clobber the previously-assembled code.  Also, be aware that the
  99. size of the output program file is determined by the value of the
  100. code segment output pointer when the program stops.  If you ORG
  101. to a lower value at the end of your program, the output program
  102. file will be truncated to the lower-value address.
  103.  
  104. Again, almost no program producing a .COM file will need any ORG
  105. directive in the code segment.  There is an implied ORG 0100 at
  106. the start of the program.  You just start coding instructions,
  107. and the assembler will put them in the right place.
  108.                                                               9-3
  109.  
  110. The EVEN Directive
  111.  
  112. Syntax:  EVEN  constant
  113.  
  114. The EVEN directive coerces the current output pointer to a value
  115. which is an exact multiple of the operand.  If no operand is
  116. given, a value of 2 is assumed.  In a DATA SEGMENT or STRUC, it
  117. does so by adding to the current output pointer if necessary.  In
  118. a code segment, it outputs an appropriate number of NOP
  119. instruction bytes.  EVEN is most often used in data segments,
  120. before a sequence of DW directives.  Machines beyond the original
  121. 8088 fetch words more quickly when they are aligned onto even
  122. addresses; so the EVEN directive insures that your program will
  123. have the faster access to those DW's that follow it.  Also useful
  124. are EVEN 4 for doubleword alignment, and EVEN 16 for paragraph
  125. alignment.  Be aware, though, that if you use the EVEN directive
  126. in .OBJ mode, the containing SEGMENT directive should have an
  127. alignment type at least as great as your EVEN operand, to achieve
  128. the desired alignment at its final memory location.
  129.  
  130.  
  131. Data Allocation Using DB, DW, DD, DQ, and DT
  132.  
  133. The 86 computer family supports the three fundamental data types
  134. BYTE, WORD, and DWORD.  A byte is eight bits, a word is 16 bits
  135. (2 bytes), and a doubleword is 32 bits (4 bytes).  In addition,
  136. the 87 floating point processor manipulates 8-byte quantities,
  137. which we call Q-words, and 10-byte quantities, which we call
  138. T-bytes.  The A86 data allocation statement is used to specify
  139. the bytes, words, doublewords, Q-words, and T-bytes which your
  140. program will use as data.  The syntax for the data allocation
  141. statement is as follows:
  142.  
  143. (optional var-name)  DB  (list of values)
  144. (optional var-name)  DW  (list of values)
  145. (optional var-name)  DD  (list of values)
  146. (optional var-name)  DQ  (list of values)
  147. (optional var-name)  DT  (list of values)
  148.  
  149. The variable name, if present, causes that name to be entered
  150. into the symbol table as a memory variable with type BYTE (for
  151. DB), WORD (for DW), DWORD (for DD), QWORD (for DQ), or TBYTE (for
  152. DT). The variable name should NOT have a colon after it, unless
  153. you wish the name to be a label (instructions referring to it
  154. will interpret the label as the constant pointer to the memory
  155. location, not its contents).
  156.  
  157. The DB statement is used to reserve bytes of storage; DW is used
  158. to reserve words.  The list of values to the right of the DB or
  159. DW serves two purposes.  It specifies how many bytes or words are
  160. allocated by the statement, as well as what their initial values
  161. should be.  The list of values may contain a single value or more
  162. than one, separated by commas.  The list can even be missing;
  163. meaning that we wish to define a byte or word variable at the
  164. same location as the next variable.
  165.                                                               9-4
  166.  
  167. If the data initialization is in the DATA segment, the values
  168. given are ignored, except as place markers to reserve the
  169. appropriate number of units of storage.  The use of "?", which in
  170. .COM mode is a synonym for zero, is recommended in this context
  171. to emphasize the lack of actual memory initialization. When A86
  172. is assembling .OBJ files, the ?-initialization will cause a break
  173. in the segment (unless ? is embedded in a nested DUP containing
  174. non-? terms, in which case it is a synonym for zero).
  175.  
  176. A special value which can be used in data initializations is the
  177. DUP construct, which allows the allocation and/or initialization
  178. of blocks of data.  The expression  n DUP x  is equivalent to a
  179. list with x repeated n times.  "x" can be either a single value,
  180. a list of values, or another DUP construct nested inside the
  181. first one.  The nested DUP construct needs to be surrounded by
  182. parentheses.  All other assemblers, and earlier versions of A86,
  183. require parentheses around all right operands to DUP, even simple
  184. ones; but this requirement has been removed for simple operands
  185. in the current A86.
  186.  
  187. Here are some examples of data initialization statements, with
  188. and without DUP constructs:
  189.  
  190. CODE SEGMENT
  191.   DW 5                  ; allocate one word, init. to 5
  192.   DB 0,3,0              ; allocate three bytes, init. to 0,3,0
  193.   DB 5 DUP 0            ; equivalent to DB 0,0,0,0,0
  194.   DW 2 DUP (0,4 DUP 7)  ; equivalent to DW 0,7,7,7,7,0,7,7,7,7
  195.  
  196.  
  197. DATA SEGMENT
  198. XX      DW ?            ; define a word variable XX
  199. YYLOW   DB              ; no init value: YYLOW is low byte of word var YY
  200. YY      DW ?
  201. X_ARRAY DB  100 DUP ?   ; X_ARRAY is a 100-byte array
  202. D_REAL  DQ ?            ; double precision floating variable
  203. EX_REAL DT ?            ; extended precision floating variable
  204.  
  205. A character string value may be used to initialize consecutive
  206. bytes in a DB statement.  Each character will be represented by
  207. its ASCII code.  The characters are stored in the order that they
  208. appear in the string, with the first character assigned to the
  209. lowest-addressed byte.  In the DB statement that follows, five
  210. bytes are initialized with the ASCII representation of the
  211. characters in the string 'HELLO':
  212.  
  213. DB 'HELLO'
  214.                                                               9-5
  215.  
  216. Note that except for string comparisons described in the previous
  217. chapter, the DB directive is the only place in your program that
  218. strings of length greater than 2 may occur.  In all other
  219. contexts (including DW), a string is treated as the constant
  220. number representing the ASCII value of the string; for example,
  221. CMP AL,'@' is the instruction comparing the AL register with the
  222. ASCII value of the at-sign.  Note further that 2-character string
  223. constants, like all constants in the 8086, have their bytes
  224. reversed.  Thus, while DB 'AB' will produce hex 41 followed by
  225. hex 42, the similar looking DW 'AB' reverses the bytes: hex 42
  226. followed by hex 41.
  227.  
  228. For compatibility, A86 now accepts double quotes, as well as
  229. single quotes, for strings in DB directives.
  230.  
  231.  
  232. The DD directive is used to initialize 32-bit doubleword pointers
  233. to locations in arbitrary segments of the 86's memory space.
  234. Values for such pointers are given by two numbers separated by a
  235. colon.  The segment register value appears to the left of the
  236. colon; and the offset appears to the right of the colon.  In
  237. keeping with the reversed-bytes nature of memory storage in the
  238. 86 family, the offset comes first in memory.  For example, the
  239. statement
  240.  
  241.    DD   01234:05678
  242.  
  243. appearing in a CODE segment will cause the hex bytes 78 56 34 12
  244. to be generated, which is a long pointer to segment 01234, offset
  245. 05678.
  246.  
  247. DD, DQ, and DT can also be used to initialize large integers and
  248. floating point numbers.  Examples:
  249.  
  250.   DD 500000   ; half million, too big for most 86 instructions
  251.   DD 3.5      ; single precision floating point number
  252.   DQ 3.5      ; the same number in a double precision format
  253.   DT 3.5      ; the same number in an extended precision format
  254.  
  255.  
  256. The STRUC Directive
  257.  
  258. The STRUC directive is used to define a template of data to be
  259. addressed by one of the 8086's base and/or index registers.  The
  260. syntax of STRUC is as follows:
  261.  
  262. (optional strucname)  STRUC  (optional effective address)
  263.  
  264. The optional structure name given at the beginning of the line
  265. can appear in subsequent expressions in the program, with the
  266. operator TYPE applied to it, to yield the number of bytes in the
  267. structure template.
  268.                                                               9-6
  269.  
  270. The STRUC directive causes the assembler to enter a mode similar
  271. to DATA SEGMENT: assembly within the structure declares symbols
  272. (the elements of the structure), using a location counter that
  273. starts out at the address following STRUC.  If no address is
  274. given, assembly starts at location 0.  An option not available to
  275. the DATA SEGMENT is that the address can include one base
  276. register [BX] or [BP] and/or one index register [SI] or [DI]. The
  277. registers are part of the implicit declaration of all structure
  278. elements, with the offset value increasing by the number of bytes
  279. allocated in each structure line. For example:
  280.  
  281. LINE STRUC [BP]        ; the template starts at [BP]
  282.        DB 80 DUP (?)   ; these 80 bytes advance us to [BP+80]
  283. LSIZE  DB ?            ; this 1 byte advances us to [BP+81]
  284. LPROT  DB ?
  285.      ENDS
  286.  
  287. The STRUC just given defines the variables LSIZE, equivalent to
  288. B[BP+80], and LPROT, equivalent to B[BP+81].  You can now issue
  289. instructions such as MOV AL,LSIZE; which automatically generates
  290. the correct indexing for you.
  291.  
  292. The mode entered by STRUC is terminated by the ENDS directive,
  293. which returns the assembler to whatever segment (CODE or DATA) it
  294. was in before the STRUC, with the location counter restored to
  295. its value within that segment before the STRUC was declared.
  296.  
  297.  
  298.  
  299. Forward References
  300.  
  301. A86 allows names for a variety of program elements to be forward
  302. referenced.  This means that you may use a symbol in one
  303. statement and define it later with another statement.  For
  304. example:
  305.  
  306.   JNZ TARGET
  307.   .
  308.   .
  309. TARGET:
  310.   ADD AX,10
  311.  
  312. In this example, a conditional jump is made to TARGET, a label
  313. farther down in the code.  When JNZ TARGET is seen, TARGET is
  314. undefined, so this is a forward reference.
  315.                                                               9-7
  316.  
  317. Earlier versions of A86 were much more restricted in the kinds of
  318. forward references allowed.  Almost all of the restrictions have
  319. now been eased, for convenience as well as compatibility with
  320. other assemblers.  In particular, you may now make forward
  321. references to variable names.  You just need to see to it that
  322. A86 has enough information about the type of the operand to
  323. generate the correct instruction.  For example, MOV FOO,AL will
  324. cause A86 to correctly deduce that FOO is a byte variable.  You
  325. can even code a subsequent MOV FOO,1 and A86 will remember that
  326. FOO was assumed to be a byte variable.  But if you code MOV FOO,1
  327. first, A86 won't know whether to issue a byte or a word MOV
  328. instruction; and will thus issue an error message.  You then
  329. specify the type by MOV FOO B,1.
  330.  
  331. In general, A86's compatibility with other assemblers has
  332. improved dramatically for forward references.  You'll need only
  333. sprinkle a very few B's and W's into your references.  And you'll
  334. be rewarded: in many cases the word form is longer than the byte
  335. form, so that other assemblers wind up inserting a wasted NOP in
  336. your program.  You'll wind up with tighter code by using A86!
  337.  
  338.  
  339. Forward References in Expressions
  340.  
  341. A86 now allows you to include any number of forward-reference
  342. symbols in expressions of arbitrary complexity.  If the
  343. expression is legal when the forward references are resolved,
  344. then it will be accepted by the assembler.
  345.  
  346. A86 will also accept the reserved symbol END as a
  347. forward-reference quantity, either by itself as an operand, or
  348. within an expression.  END will be resolved when assembly is
  349. complete, as a label pointing to the end of the program.
  350.  
  351. For example, suppose you wish to advance the ES segment register
  352. to point immediately beyond your program.  You can code:
  353.  
  354.      MOV AX,CS           ; fetch the program's segment value
  355.      ADD AX,(END+15)/16  ; add in the number of paragraphs
  356.      MOV ES,AX           ; ES is now loaded as desired
  357.  
  358.  
  359.  
  360. The EQU Directive
  361.  
  362. Syntax:  symbol-name    EQU expression
  363.          symbol-name    EQU built-in-symbol
  364.          symbol-name    EQU INT n
  365.  
  366. The expression field may specify an operand of any type that
  367. could appear as an operand to an instruction.
  368.                                                               9-8
  369.  
  370. As a simple example, suppose you are writing a program that
  371. manipulates a table containing 100 names and that you want to
  372. refer to the maximum number of names throughout the source file.
  373. You can, of course, use the number 100 to refer to this maximum
  374. each time, as in MOV CX,100, but this approach suffers from two
  375. weaknesses.  First of all, 100 can mean a lot of things; in the
  376. absence of comments, it is not obvious that a particular use of
  377. 100 refers to the maximum number of names.  Secondly, if you
  378. extend the table to allow 200 names, you will have to locate each
  379. 100 and change it to a 200.  Suppose, instead, that you define a
  380. symbol to represent the maximum number of names with the
  381. following statement:
  382.  
  383. MAX_NAMES EQU 100
  384.  
  385. Now when you use the symbol MAX_NAMES instead of the number 100
  386. (for example, MOV CX,MAX_NAMES), it will be obvious that you are
  387. referring to the maximum number of names in the table.  Also, if
  388. you decide to extend the table, you need only change the 100 in
  389. the EQU directive to a 200 and every reference to MAX_NAMES will
  390. reflect the change.
  391.  
  392. You could also take advantage of A86's strong typing, by changing
  393. MAX_NAMES to a variable:
  394.  
  395. MAX_NAMES  DB ?
  396.  
  397. or even an indexed quantity:
  398.  
  399. MAX_NAMES EQU [BX+1]
  400.  
  401. Because the A86 language is strongly typed, the instruction for
  402. loading MAX_NAMES into the CX register remains exactly the same
  403. in all cases: simply MOV CX,MAX_NAMES.
  404.  
  405.  
  406. Equates to Built-In Symbols
  407.  
  408. A86 allows you to define synonyms for any of the assembler
  409. reserved symbols, by EQUating an alternate name of your choosing,
  410. to that symbol.  For example, suppose you were coding a source
  411. module that is to be incorporated into several different
  412. programs.  In some programs, a certain variable will exist in the
  413. code segment.  In others, it will exist in the stack segment. You
  414. want to address the variable in the common source module, but you
  415. don't know which segment override to use.  The solution is to
  416. declare a synonym, QS, for the segment register.  QS will be
  417. defined by each program: the code-segment program will have a QS
  418. EQU CS at the top of it; the stack-segment program will have QS
  419. EQU SS.  The source module can use QS as an override, just as if
  420. it were CS or SS.  The code would be, for example, QS MOV
  421. AL,VARNAME.
  422.                                                               9-9
  423.  
  424. The NIL Prefix
  425.  
  426. A86 provides a mnemonic, NIL, that generates no code.  NIL can be
  427. used as a prefix to another instruction (which will have no
  428. effect on that instruction), or it can appear by itself on a
  429. line.  NIL is provided to extend the example in the previous
  430. section, to cover the possibility of no overrides.  If your
  431. source module goes into a program that fits into 64K, so that all
  432. the segment registers have the same value, then code QS EQU NIL
  433. at the top of that program.
  434.  
  435.  
  436. Interrupt Equates
  437.  
  438. A86 allows you to equate your own name to an INT instruction with
  439. a specific interrupt number.  For example, if you place  TRAP EQU
  440. INT 3  at the top of your program, you can use the name TRAP as a
  441. synonym for INT 3  (the debugger trap on the 8086).
  442.  
  443.  
  444. Duplicate Definitions
  445.  
  446. A86 contains the unique feature of duplicate definitions.   We
  447. have already discussed local symbols, which can be redefined to
  448. different values without restriction.  Local symbols are the only
  449. symbols that can be redefined.  However, any symbol can be
  450. defined more than once, as long as the symbol is defined to be
  451. the same value and type in each definition.
  452.  
  453. This feature has two uses.  First, it eases modular program
  454. development.  For example, if two independently-developed source
  455. files both use the symbol ESC to stand for the ASCII code for
  456. ESCAPE, they can both contain the declaration ESC EQU 01B, with
  457. no problems if they are combined into the same program.
  458.  
  459. The second use for this feature is assertion checking.  Your
  460. deliberate redeclaration of a symbol name is an assertion that
  461. the value of the symbol has not changed; and you want the
  462. assembler to issue you an error message if it has changed.
  463. Example: suppose you have declared a table of options in your
  464. DATA segment; and you have another table of initial values for
  465. those options in your CODE segment.  If you come back months
  466. later and add an option to your tables, you want to be reminded
  467. to update both tables in the same way.  You should declare your
  468. tables as follows:
  469.  
  470. DATA SEGMENT
  471.   OPTIONS:
  472.     .
  473.     .
  474.   OPT_COUNT EQU $-OPTIONS    ; OPT_COUNT is the size of the table
  475.  
  476. CODE SEGMENT
  477.   OPT_INITS:
  478.     .
  479.     .
  480.   OPT_COUNT EQU $-OPT_INITS  ; second OPT_COUNT had better be the same!
  481.                                                              9-10
  482.  
  483. The = Directive
  484.  
  485. Syntax:  symbol-name = expression
  486.          symbol-name = built-in-symbol
  487.          symbol-name = INT n
  488.  
  489. The equals sign directive is provided for compatibility.  It is
  490. identical to the EQU directive, with one exception: if the first
  491. time a symbol appears in a program is in an = directive, that
  492. symbol will be taken as a local symbol.  It can be redefined to
  493. other values, just like the generic local symbols (letter
  494. followed by digits) that A86 supports. (If you try to redefine an
  495. EQU symbol to a different value, you get an error message.) The =
  496. facility is most often used to define "assembler variables", that
  497. change value as the assembly progresses.
  498.  
  499.  
  500. The PROC Directive
  501.  
  502. Syntax:   name  PROC NEAR
  503.           name  PROC FAR
  504.           name  PROC
  505.  
  506. PROC is a directive provided for compatibility with Intel/IBM
  507. assemblers.  I don't like PROC; and I recommend that you do not
  508. use it, even if you are programming for those assemblers.
  509.  
  510. The idea behind PROC is to give the assembler a mechanism whereby
  511. it can decide for you what kind of RET instruction you should be
  512. providing.  If you specify NEAR in your PROC directive, then the
  513. assembler will generate a near (same segment) return when it sees
  514. RET.  If you specify FAR in your PROC directive, the assembler
  515. will generate a far RETF return (which will cause both IP and CS
  516. to be popped from the stack).  If you simply leave well enough
  517. alone, and never code a PROC in your program, then RET will mean
  518. near return throughout your program.
  519.  
  520. The reason I don't like PROC is because it is yet another attempt
  521. by the assembler to do things "behind your back".  This goes
  522. against the reason why you are programming in assembly language
  523. in the first place, which is to have complete control over the
  524. code generated by your source program.  It leads to nothing but
  525. trouble and confusion.
  526.  
  527. Another problem with PROC is its verbosity.  It replaces a simple
  528. colon, given right after the label it defines.  This creates a
  529. visual clutter in the program, that makes the program harder to
  530. read.
  531.  
  532. A86 provides an explicit RETF mnemonic so that you don't need to
  533. use PROC to distinguish between near and far return instructions.
  534. You can use RET for a near return and RETF for a far return.
  535.                                                              9-11
  536.  
  537. The ENDP Directive
  538.  
  539. Syntax:  [name] ENDP
  540.  
  541. The only action A86 takes when it sees an ENDP directive is to
  542. return the assembler to its (sane) default state, in which RET is
  543. a near return.
  544.  
  545. NOTE that this means that A86 does not support nested PROCs, in
  546. which anything but the innermost PROC has the FAR attribute.  I'm
  547. sorry if I am blunt, but anybody who would subject their program
  548. to that level of syntactic clutter has rocks in their head.
  549.  
  550.  
  551. The LABEL Directive
  552.  
  553. Syntax:  name LABEL NEAR
  554.          name LABEL FAR
  555.          name LABEL BYTE
  556.          name LABEL WORD
  557.          name LABEL DWORD
  558.          name LABEL QWORD
  559.          name LABEL TBYTE
  560.  
  561. LABEL is another directive provided for compatibility with
  562. Intel/IBM assemblers.  A86 provides less verbose ways of
  563. specifying all the above LABEL forms, except for LABEL FAR.
  564.  
  565. LABEL defines "name" to have the type given, and a value equal to
  566. the current output pointer.  Thus, LABEL NEAR is synonymous with
  567. a simple colon following the name; and LABEL BYTE, LABEL WORD,
  568. LABEL DWORD, etc., are synonymous with DB, DW, DD, etc., with no
  569. operands.
  570.  
  571. LABEL FAR does have a unique functionality, not found in other
  572. assemblers.  It identifies "name" as a procedure that can be
  573. called from outside this program's code segment.  Such procedures
  574. should have RETFs instead of RETs. Furthermore, I have provided
  575. the following feature, unique to A86: if you CALL the procedure
  576. from within your program, A86 will generate a PUSH CS instruction
  577. followed by a NEAR call to the procedure.  Other assemblers will
  578. generate a FAR call, having the same functional effect; but the
  579. FAR call consumes more program space, and takes more time to
  580. execute.
  581.  
  582. WARNING: you cannot use the above CALL feature as a forward
  583. reference; the LABEL FAR definition must precede any CALLs to it.
  584. This is unavoidable, since the assembler must assume that a CALL
  585. to an undefined symbol takes 3 program bytes.  All assemblers
  586. will issue an error in this situation.
  587.                                                              9-12
  588.  
  589. The INCLUDE Directive
  590.  
  591. A86 now allows the inclusion of alternate source files within the
  592. middle of a "parent" source file, via the INCLUDE directive.
  593. When you give the name INCLUDE followed by the name of a file,
  594. A86 will insert the contents of the named file into the assembly
  595. source stream, as if it were substituted for the INCLUDE line.
  596. There is no limit to the size of an INCLUDE file, and INCLUDEs
  597. may be nested (the file included may itself contain INCLUDE
  598. directives) to any level within reason.  Parentheses are optional
  599. around the file name; if you don't give them, there must be at
  600. least one blank between the INCLUDE and the file name.
  601.  
  602. If there is no file name whatever following the INCLUDE, A86 will
  603. perform an A86LIB library search (see Chapter 13), and INCLUDE
  604. all library files necessary to resolve all undefined symbols at
  605. the point of the INCLUDE.  This provides an "in-file" equivalent
  606. to the pound-sign given on the invocation line.
  607.  
  608.