|
|
1.1 root 1:
2:
3: as Command as
4:
5:
6:
7:
8: i8086 assembler
9:
10: aass [-ggllxx] [ -oo_f_i_l_e ] _f_i_l_e ...
11:
12: as is the Mark Williams assembler. It is a multipass assembler
13: that turns files of assembly language into relocatable object
14: modules similar to those produced by the compiler. as is
15: designed for writing small assembly-language subroutines.
16: Because it is not intended to be used for full-scale assembly-
17: language programming, it lacks many of the more elaborate
18: facilities of full-fledged assemblers. For example, there are no
19: facilities for conditional compilation or user-defined macros.
20: However, it does optimize span-dependent instructions (for ex-
21: ample, branches).
22:
23: ***** Features *****
24:
25: as includes the following features:
26:
27: * It automatically compiles jump instructions into either
28: regular (three-byte) jumps or short (two-byte) jumps,
29: whichever is required. There is no explicit short jump in-
30: struction.
31:
32: * The assembler supports temporary labels, which conserves sym-
33: bol table space and relieves the you of having to invent many
34: unique labels.
35:
36: * Program modules are relocatable. They can be linked with each
37: other and with C program modules produced by the COHERENT com-
38: piler. All assembled modules must be linked before they can
39: be executed.
40:
41: * The assembler does not support file inclusion, but multiple
42: source files can be concatenated and assembled by including
43: their names in the command line to run the assembler.
44:
45: * The assembler generates SMALL model objects in the COHERENT
46: l.out object format.
47:
48: ***** Usage *****
49:
50: Normally, the assembler is invoked via the cccc command, which will
51: automatically assemble and link any file of source code that has
52: the suffix .ss. If you wish, however, you can invoke the as-
53: sembler as a separate program, by using the following command
54: line:
55:
56:
57: aass [-ggllxx] [ -oo _f_i_l_e ] _f_i_l_e ...
58:
59:
60: The named _f_i_l_es are concatenated and the resulting object code is
61: written to the file specified by the -o option, or to file l.out
62:
63:
64: COHERENT Lexicon Page 1
65:
66:
67:
68:
69: as Command as
70:
71:
72:
73: if no -o option is given.
74:
75: The option -g causes all symbols that are undefined at the end of
76: the first pass to be given the type undefined external, as though
77: they had been declared with a .globl directive.
78:
79: The option -l tells the assembler to generate a listing. It
80: writes the listing to the standard output, normally the terminal;
81: it may be easily redirected to a file or printer using the >
82: operator.
83:
84: The option -x strips from the symbol table of the object module
85: all non-global symbols that begin with the character `L'. This
86: speeds up the loading of files by removing compiler-generated
87: labels from the symbol table.
88:
89: ***** Register Names *****
90:
91: The following lists the identifiers that represent the i8086
92: machine registers, which are predefined:
93:
94:
95: AX SP AL AH CS
96: BX BP BL BH DS
97: CX SI CL CH ES
98: DX DI DL DH SS
99:
100:
101: ***** Lexical Conventions *****
102:
103: Assembler tokens consist of identifiers (also known as ``sym-
104: bols'' or ``names''), constants, and operators.
105:
106: An identifier is a sequence of alphanumeric characters (including
107: the period `.' and the underscore `_'). The first character must
108: not be numeric. Only the first 16 characters of the name are
109: significant; it throws away the remainder. Upper case and lower
110: case are different. The machine instructions, assembly direc-
111: tives, and built-in symbols that are used frequently are in lower
112: case.
113:
114: Numeric constants are defined by the assembler by using the same
115: syntax as the C compiler: a sequence of digits that begins with a
116: zero `0' is an octal constant; a sequence of digits with a
117: leading `0x' is a hexadecimal constant (`A' through `F' have the
118: decimal values 10 through 15); and any strings of digits that do
119: not begin with `0' are interpreted as decimal constants.
120:
121: A character constant consists of an apostrophe followed by an
122: ASCII character. The constant's value is the ASCII code for the
123: character, right-justified in the machine word. For example, an
124: instruction to move the letter `A' to the register al could be
125: expressed in either of two equivalent ways:
126:
127:
128:
129:
130: COHERENT Lexicon Page 2
131:
132:
133:
134:
135: as Command as
136:
137:
138:
139:
140: mov al,$0x41
141: mov al,$'A
142:
143:
144: The dollar sign indicates an immediate operand.
145:
146: A blank space can be represented either 00xx2200 (its ASCII value in
147: hexadecimal), or as an apostrophe followed by a space (' ), which
148: on paper looks like just an apostrophe alone.
149:
150: The following gives the multi-character escape sequences that can
151: be used in a character constant to represent special characters:
152:
153:
154: \bb Backspace (0010)
155: \ff Formfeed (0014)
156: \nn Newline (0012)
157: \rr Carriage return(0015)
158: \tt Tab (0011)
159: \vv Vertical tab (0013)
160: \_n_n_n Octal value (0_n_n_n)
161:
162:
163: A blank space can be represented either as 0x20 (its ASCII value
164: in hexadecimal), or as an apostrophe followed by a space (' ),
165: which on the page would look like just an apostrophe.
166:
167: ***** Blanks and Tabs *****
168:
169: Blanks and tab characters may be used freely between tokens, but
170: not within identifiers. A blank or a tabulation character is
171: required to separate adjacent tokens not otherwise separated,
172: e.g., between an instruction opcode and its first operand.
173:
174: ***** Comments *****
175:
176: Comments are introduced by a slash (`/') and continue until the
177: end of the line. All characters in comments are ignored by the
178: assembler.
179:
180: ***** Program Sections *****
181:
182: The assembler permits you to divide programs into sections, each
183: corresponding (roughly) to a functional area of the address
184: space. Each program section has its own location counter during
185: assembly. There are eight program sections, subdivided into
186: three groups containing code, data and tables:
187:
188:
189: code: sshhrrii Shared instruction
190: bbssssii Uninitialized instruction
191: pprrvvii Private instruction
192: data: pprrvvdd Private data
193: sshhrrdd Shared data
194:
195:
196: COHERENT Lexicon Page 3
197:
198:
199:
200:
201: as Command as
202:
203:
204:
205: bbssssdd Uninitialized data
206: ssttrrnn Strings
207: tables: ssyymmtt Symbol table
208:
209:
210: All Mark Williams assemblers use the same set of sections. This
211: increases the portability of programs between operating systems.
212: Not all the sections are distinct under COHERENT, however; the
213: meanings of the sections under (including hints as to how the C
214: compiler uses them) are as follows:
215:
216: shri (shared instruction) is the same as prvi (private instruc-
217: tion); the adjective shared refers to the sharing of physical
218: memory between two or more concurrent processes. prvi is used
219: for all code generated by the C compiler.
220:
221: Similarly, there is no distinction between shrd and prvd. The
222: compiler uses the latter for all external and static data that
223: are explicitly initialized in a C program.
224:
225: Uninitialized sections are actually initialized to zeros. The
226: reason is that the C compiler uses the bssd (uninitialized data)
227: section for external or static data that are not explicitly in-
228: itialized: the C language guarantees that these data are in fact
229: initialized to zeros. The bssi (uninitialized instruction) sec-
230: tion is not used by the compiler.
231:
232: The strn (strings) section is actually a special part of the data
233: section, used by the C compiler to store string constants. It is
234: synonymous with prvd under COHERENT.
235:
236: The symt (symbol table) section contains the symbol table used by
237: the linker. Both the C compiler and the assembler generate sym-
238: bol tables that go in this section.
239:
240: In most cases, you need not worry about what all these program
241: sections are, and can simply write code under the keyword .prvi
242: or .shri, and write data under the keyword .prvd or .shrd. You
243: are advised not to place items in the symt section, as this sec-
244: tion is used for internal communication among the C compiler, the
245: assembler, and the linker.
246:
247: At the end of assembly, the sections of a program are con-
248: catenated so that in the assembly listing the program looks like
249: a monolithic block of code and data. All ccooddee sections are com-
250: bined into the i8086 ccooddee segment, and all ddaattaa sections into the
251: i8086 ddaattaa segment. The symbol table is not linked when the
252: program is executed, and so is not assigned to any i8086 segment.
253:
254: ***** The Current Location *****
255:
256: The special symbol `.' (period) is a counter that represents the
257: current location. The current location can be changed by an as-
258: signment; for example:
259:
260:
261:
262: COHERENT Lexicon Page 4
263:
264:
265:
266:
267: as Command as
268:
269:
270:
271:
272: . = .+START
273:
274:
275: The assignment must not cause the value to decrease, and it must
276: not change the program section, i.e., the right-hand operand must
277: be defined in the same section as the current section.
278:
279: ***** Expressions *****
280:
281: An expression is a sequence of symbols representing a value and a
282: program section. Expressions are made up of identifiers, con-
283: stants, operators, and brackets. All binary operators have equal
284: precedence and are executed in a strict left-to-right order (un-
285: less altered by brackets).
286:
287: Notice that square brackets, `[' and `]', group expression
288: elements, because parentheses are used for indexed register ad-
289: dressing.
290:
291: ***** Types *****
292:
293: Every expression has a type determined by its operands. The
294: simplest operands are symbols. The types of symbols are as
295: follows:
296:
297: Undefined A symbol is defined if it is a constant or a label, or
298: when assigned a defined value; otherwise, it is un-
299: defined. A symbol may become undefined if it is as-
300: signed the value of an undefined expression. It is an
301: error to assemble an undefined expression in pass 2.
302: Pass 1 allows assembly of undefined expressions, but
303: phase errors may be produced if undefined expressions
304: are used in certain contexts, such as in a .blkw or
305: .blkb.
306:
307: Absolute An absolute symbol is one defined ultimately from a
308: constant or from the difference of two relocatable
309: values.
310:
311: Register These are the machine registers.
312:
313: Relocatable
314: All other user symbols are relocatable symbols in some
315: program section. Each program section is a different
316: relocatable type.
317:
318: Each keyword in the assembler has a secret type that identifies
319: it internally; however, all of these secret types are converted
320: to absolute in expressions. Thus, any keyword may be used in an
321: expression to obtain the basic value of the keyword. This is
322: useful when employing the keywords that define machine instruc-
323: tions. The basic value of a machine operation is usually the op-
324: code with any operand-specific bits set to zero.
325:
326:
327:
328: COHERENT Lexicon Page 5
329:
330:
331:
332:
333: as Command as
334:
335:
336:
337: Notice that the type of an expression does not include such at-
338: tributes as length (word or byte), so the assembler will not
339: remember whether you defined a particular variable to be a word
340: or a byte. Addresses and constants have different types, but the
341: assembler does not treat a constant as an immediate value unless
342: it is preceded by a dollar sign `$'. If you use a constant where
343: an address is expected, aass will treat the constant like an ad-
344: dress (and vice versa). It is up to you to distinguish between
345: variables and addresses or immediate values.
346:
347: ***** Operators *****
348:
349: The following figure shows various characters interpreted as
350: operators in expressions.
351:
352:
353: + Addition
354: - Subtraction
355: * Multiplication
356: - Unary negation
357: ~ Unary complement
358: ^ Type transfer
359: | Segment construction
360:
361:
362: You can group expressions by means of square brackets (`[' and
363: `]'); parentheses are reserved for use in address mode descrip-
364: tions.
365:
366: ***** Type Propagation *****
367:
368: When operands are combined in expressions, the resulting type is
369: a function of both the operator and the types of the operands.
370: The operators `*', `~', and unary `-' can only manipulate ab-
371: solute operands and always yield an absolute result.
372:
373: The operator `+' signifies the addition of two absolute operands
374: to yield an absolute result, and the addition of an absolute to a
375: relocatable operand to yield a result with the same type as the
376: relocatable operand.
377:
378: The binary operator `-' allows two operands of the same type, in-
379: cluding relocatable, to be subtracted to yield an absolute
380: result. It also allows an absolute to be subtracted from a
381: relocatable, to yield a result with the same type as the relocat-
382: able operand.
383:
384: The binary operator `^' yields a result with the value of its
385: left operand and the type of its right operand. It may be used
386: to create expressions (usually intended to be used in an assign-
387: ment statement) with any desired type.
388:
389: ***** Statements *****
390:
391: A program consists of a sequence of statements separated by
392:
393:
394: COHERENT Lexicon Page 6
395:
396:
397:
398:
399: as Command as
400:
401:
402:
403: newlines or by semicolons. There are four kinds of statements:
404: null statements, assignment statements, keyword statements, and
405: machine instructions.
406:
407: ***** Labels *****
408:
409: You can precede any statement by any number of labels. There are
410: two kinds of labels: _n_a_m_e _l_a_b_e_l_s and _t_e_m_p_o_r_a_r_y _l_a_b_e_l_s.
411:
412: A name label consists of an identifier followed by a colon (:).
413: The program section and value of the label are set to that of the
414: current location counter. It is an error for the value of a
415: label to change during an assembly. This most often happens when
416: an undefined symbol is used to control a location counter adjust-
417: ment.
418:
419: A temporary label consists of a digit (00 to 99) followed by a
420: colon (:). Such a label defines temporary symbols of the form
421: xxff and xxbb, where xx is the digit of the label. References of the
422: form xxff refer to the first temporary label xx: forward from the
423: reference; those of the form xxbb refer to the first temporary
424: label xx: backward from the reference. Such labels conserve sym-
425: bol table space in the assembler.
426:
427: ***** Null Statements *****
428:
429: A null statement is an empty line, or a line containing only
430: labels or a comment. Null statements can occur anywhere. They
431: are ignored by the assembler, except that any labels are given
432: the current value of the location counter.
433:
434: ***** Assignment Statements *****
435:
436: An assignment statement consists of an identifier followed by an
437: equal sign `=' and an expression. The value and program section
438: of the identifier are set to that of the expression. Any symbol
439: defined by an assignment statement may be redefined, either by
440: another assignment statement or by a label. An assignment
441: statement is equivalent to the equ keyword statement found in
442: many assemblers.
443:
444: ***** Assembler Directives *****
445:
446: Assembler directives give instructions to the assembler. Each
447: directive keyword begins with a period, and in general they are
448: followed by operands.
449:
450: The following directives change the current program section to
451: the named section:
452:
453:
454:
455:
456:
457:
458:
459:
460: COHERENT Lexicon Page 7
461:
462:
463:
464:
465: as Command as
466:
467:
468:
469: .bssd
470: .bssi
471: .prvd
472: .prvi
473: .shrd
474: .shri
475: .strn
476: .symt
477:
478:
479: The current location counter is set to the highest previous value
480: of the location counter for the selected section.
481:
482: The following describes the directives in detail.
483:
484: .aasscciiii _s_t_r_i_n_g
485: The first non-white space character, typically a quotation
486: mark, after the keyword is taken as a delimiter. as as-
487: sembles successive characters from the string into succes-
488: sive bytes until it encounters the next instance of this
489: delimiter. To include a quotation mark in a string, use
490: some other character for the delimiter.
491:
492: It is an error for a newline to be encountered before
493: reaching the final delimiter. You can use a multi-character
494: constant in the string to represent newlines and other
495: special characters.
496:
497: .bbllkkbb _e_x_p_r_e_s_s_i_o_n
498: Assemble a block of bytes that are filled with zeroes. The
499: block is expression bytes long.
500:
501: .bbllkkww _e_x_p_r_e_s_s_i_o_n
502: Assemble a block of words that are filled with zeroes. The
503: block is expression words long.
504:
505: .bbyyttee _e_x_p_r_e_s_s_i_o_n [, _e_x_p_r_e_s_s_i_o_n ]
506: The _e_x_p_r_e_s_s_i_o_ns in the list are truncated to byte size and
507: assembled into successive bytes. Expressions in the list
508: are separated by commas.
509:
510: .eevveenn
511: Force alignment by inserting a null byte of data, if neces-
512: sary, to set the location counter to the next even location.
513:
514: .oodddd
515: Force alignment by inserting a null byte of data, if neces-
516: sary, to set the location counter to the next odd location.
517:
518: .gglloobbll _i_d_e_n_t_i_f_i_e_r [, _i_d_e_n_t_i_f_i_e_r ]
519: The identifiers in the comma-separated list are marked as
520: global. If they are defined in the current assembly, they
521: may be referenced by other object modules; if they are un-
522: defined, they must be resolved by the linker before execu-
523: tion.
524:
525:
526: COHERENT Lexicon Page 8
527:
528:
529:
530:
531: as Command as
532:
533:
534:
535:
536: .ppaaggee
537: Force the printed listing of your assembly-language program
538: to skip to the top of a new page by inserting a form-feed
539: character into the file. The title is printed at the top of
540: the page.
541:
542: .ttiittllee _s_t_r_i_n_g
543: Print string at the top of every page in the listing. This
544: directive also causes the listing to skip to a new page.
545:
546: .wwoorrdd _e_x_p_r_e_s_s_i_o_n [, _e_x_p_r_e_s_s_i_o_n ]
547: Truncate _e_x_p_r_e_s_s_i_o_ns to word length and assemble the resul-
548: ting data into successive words. Expressions in the list
549: are separated by commas.
550:
551: ***** Address Descriptors *****
552:
553: The following syntax is used for general source and destination
554: address descriptors. The symbol `r' refers to a register and the
555: symbol `e' to an expression. Please refer to the following
556: figure.
557:
558:
559: _S_y_n_t_a_x _A_d_d_r_e_s_s_i_n_g _M_o_d_e _E_x_a_m_p_l_e
560:
561: r Register mov ax, cx
562: e Direct address mov ax, 0800
563: (r) Indexing, no displacement movax, (bx)
564: e(r) Indexing with displacement movax, 2(bx)
565: (r,r) Double indexing, no displacementmov ax, (bx, si)
566: e(r,r) Double indexing with displacementmov ax, 2(bx, si)
567: $e Immediate mov ax, $0800
568:
569:
570: Note that the dollar sign is always used to indicate an immediate
571: value, even if the expression is a constant.
572:
573: A direct address is interpreted as either a direct address or a
574: PC-relative displacement, depending on the requirements of the
575: instruction.
576:
577: If an address descriptor indicates an indexing mode and the base
578: expression is of type absolute, the assembler uses the shortest
579: displacement length (zero, one, or two bytes) that can hold the
580: expression's value. Relocatable base expressions, whose values
581: cannot be completely determined until the program is loaded, are
582: always assigned two-byte displacements.
583:
584: Any address descriptor may be modified by a segment escape
585: prefix. A segment escape prefix consists of a segment register
586: name followed by a colon `:'. The escape causes the assembler to
587: produce a segment override prefix that uses the specified segment
588: register as an operand. The assembler does not produce segment
589: override prefixes unless explicitly required by an instruction.
590:
591:
592: COHERENT Lexicon Page 9
593:
594:
595:
596:
597: as Command as
598:
599:
600:
601:
602: ***** 8086 Instructions *****
603:
604: The following machine instructions are defined. The examples
605: illustrate the general syntax of the operands. Combinations that
606: are syntactically valid may be forbidden for semantic reasons.
607:
608: The examples use the following references:
609:
610:
611: _a General address
612: _a_l AL register
613: _a_x AX register
614: _c_l CL register
615: _d Direct address
616: _d_x DX register
617: _e Expression
618: $_e Immediate expression
619: _m Memory address (not an immediate)
620: _p Port address
621:
622:
623: aass treats as ordinary one-byte machine operations some operations
624: that the Intel assembler ASM86 handles with special syntax; these
625: include the _l_o_c_k and _r_e_p_e_a_t prefixes. aass makes no attempt to
626: prevent the generation of incorrect sequences of these prefix
627: bytes.
628:
629: Although every machine operation has a type and value associated
630: with it, in most cases the value was chosen to help aass format the
631: machine instructions.
632:
633: For more information on these instructions, see the Intel ASM86
634: Assembly Language Reference Manual.
635:
636: aaaaaa ASCII adjust AL after addition
637: aaaadd ASCII adjust AX before division
638: aaaamm ASCII adjust AX after multiply
639: aaaass ASCII adjust AL after subtraction
640: aaddccbb _r, _a Add with carry, byte
641: aaddcc _r, _a Add with carry, word
642: aaddccbb _a, _r Add with carry, byte
643: aaddcc _a, _r Add with carry, word
644: aaddccbb _a, $_e Add with carry, byte
645: aaddcc _a, $_e Add with carry, word
646: aaddddbb _r, _a Add, byte
647: aadddd _r, _a Add, word
648: aaddddbb _a, _r Add, byte
649: aadddd _a, _r Add, word
650: aaddddbb _a, $_e Add, byte
651: aadddd _a, $_e Add, word
652: aannddbb _r, _a Logical and, byte
653: aanndd _r, _a Logical and, word
654: aannddbb _a, _r Logical and, byte
655: aanndd _a, _r Logical and, word
656:
657:
658: COHERENT Lexicon Page 10
659:
660:
661:
662:
663: as Command as
664:
665:
666:
667: aannddbb _a, $_e Logical and, byte
668: aanndd _a, $_e Logical and, word
669: ccaallll _d Near call, PC-relative
670: ccbbww Convert byte into word
671: ccllcc Clear carry flag
672: cclldd Clear direction flag
673: ccllii Clear interrupt flag
674: ccmmcc Complement carry flag
675: ccmmppbb _r, _a Compare two operands, byte
676: ccmmpp _r, _a Compare two operands, word
677: ccmmppbb _a, _r Compare two operands, byte
678: ccmmpp _a, _r Compare two operands, word
679: ccmmppbb _a, $_e Compare two operands, byte
680: ccmmpp _a, $_e Compare two operands, word
681: ccmmppss Compare string operands, bytes
682: ccmmppssbb Compare string operands, bytes
683: ccmmppssww Compare string operands, words
684: ccwwdd Convert word to double
685: ddaaaa Decimal adjust AL after addition
686: ddaass Decimal adjust AL after subtraction
687: ddeeccbb _a Decrement by one, byte
688: ddeecc _a Decrement by one, word
689: ddiivvbb _m Unsigned divide, byte
690: ddiivv _m Unsigned divide, word
691: eesscc _a Escape 00xxDD88
692: hhlltt Halt
693: iiccaallll _a Near call, absolute offset at EA word
694: iiddiivvbb _m Signed divide, byte
695: iiddiivv _m Signed divide, word
696: iijjmmpp _a Jump short, absolute offset at EA word
697: iimmuullbb _m Signed multiply, byte
698: iimmuull _m Signed multiply, word
699: iinnbb _a_l, _p Input, byte
700: iinn _a_x, _p Input, word
701: iinnbb _a_l, _d_x Input, byte
702: iinn _a_x, _d_x Input, word
703: iinnccbb _a Increment by one, byte
704: iinncc _a Increment by one, word
705: iinntt _e Call to interrupt
706: iinnttoo Call to interrupt, overflow
707: iirreett Interrupt return
708: jjaa _d Jump short if greater
709: jjaaee _d Jump short if greater or equal
710: jjbb _d Jump short if less
711: jjbbee _d Jump short if less or equal
712: jjcc _d Jump short if carry
713: jjccxxzz _d Jump short if CX equals zero
714: jjee _d Jump short if equal to
715: jjgg _d Jump short if greater
716: jjggee _d Jump short if greater or equal
717: jjll _d Jump short if less
718: jjllee _d Jump short if less or equal
719: jjmmpp _d Jump short, PC-relative word offset
720: jjmmppbb _d Jump short, PC-relative byte offset
721: jjmmppll _d Jump long
722:
723:
724: COHERENT Lexicon Page 11
725:
726:
727:
728:
729: as Command as
730:
731:
732:
733: jjnnaa _d Jump short if not above
734: jjnnaaee _d Jump short if not above or equal
735: jjnnbb _d Jump short if not below
736: jjnnbbee _d Jump short if not below or equal
737: jjnncc _d Jump short if not carry
738: jjnnee _d Jump short if not equal
739: jjnngg _d Jump short if not greater
740: jjnnggee _d Jump short if not greater or equal
741: jjnnll _d Jump short if not less
742: jjnnllee _d Jump short if not less or equal
743: jjnnoo _d Jump short if not overflow
744: jjnnpp _d Jump short if not parity
745: jjnnss _d Jump short if not sign
746: jjnnzz _d Jump short if not zero
747: jjoo _d Jump short if overflow
748: jjpp _d Jump short if parity
749: jjppee _d Jump short if parity even
750: jjppoo _d Jump short if parity odd
751: jjss _d Jump short if sign
752: jjzz _d Jump short if zero
753: llaahhff Load flags into AH register
754: llddss _r, _a Load double pointer into DS
755: lleeaa _r, _a Load effective address offset
756: lleess _r, _a Load double pointer into ES
757: lloocckk Assert BUS LOCK signal
758: llooddssbb Load byte into AL
759: llooddss Load byte into AL
760: llooddssww Load byte into AL
761: lloooopp _d Loop; decrement CX, jump short
762: if CX less than zero
763: llooooppee _d Loop; decrement CX, jump short
764: if CZ not zero and equal
765: llooooppnnee _d Loop; decrement CX, jump short
766: if CX not zero and not equal
767: llooooppnnzz _d Loop; decrement CX, jump short
768: if CZ not zero and ZF equals zero
769: llooooppzz _d Loop; decrement CX, jump short
770: if CX not zero and zero
771: mmoovvbb _r, _a Move, byte
772: mmoovv _r, _a Move, word
773: mmoovvbb _a, _r Move, byte
774: mmoovv _a, _r Move, word
775: mmoovvbb _a, $_e Move, byte
776: mmoovv _a, $_e Move, word
777: mmoovvbb _a, _s Move, byte
778: mmoovv _a, _s Move, word
779: mmoovvbb _s, _a Move, byte
780: mmoovv _s, _a Move, word
781: mmoovvssbb Move string byte-by-byte
782: mmoovvss Move string word-by-word
783: mmoovvssww Move string word-by-word
784: mmuullbb _m Multiply, byte
785: mmuull _m Multiply, word
786: nneeggbb _a Two's complement negation, byte
787: nneegg _a Two's complement negation, word
788:
789:
790: COHERENT Lexicon Page 12
791:
792:
793:
794:
795: as Command as
796:
797:
798:
799: nnoopp No operation
800: nnoottbb _a One's complement negation, byte
801: nnoott _a One's complement negation, word
802: oorrbb _r, _a Logical inclusive OR, byte
803: oorr _r, _a Logical inclusive OR, word
804: oorrbb _a, _r Logical inclusive OR, byte
805: oorr _a, _r Logical inclusive OR, word
806: oorrbb _a, $_e Logical inclusive OR, byte
807: oorr _a, $_e Logical inclusive OR, word
808: oouuttbb _p, _a_l Output to port, byte
809: oouutt _p, _a_x Output to port, word
810: oouuttbb _d_x, _a_l Output to port, byte
811: oouutt _d_x, _a_x Output to port, word
812: ppoopp _m Pop a word from the stack
813: ppoopp _s Pop a word from the stack
814: ppooppff Pop from stack into flags register
815: ppuusshh _m Push a word onto the stack
816: ppuusshh _s Push a word onto the stack
817: ppuusshhff Push flags register onto the stack
818: rrccllbb _a, $_1 Rotate left $1 times, byte
819: rrccllbb _a, _c_l Rotate left CL times, byte
820: rrccll _a, $_1 Rotate left $1 times, word
821: rrccll _a, _c_l Rotate left CL times, word
822: rrccrrbb _a, $_1 Rotate right $1 times, byte
823: rrccrrbb _a, _c_l Rotate right CL times, byte
824: rrccrr _a, $_1 Rotate right $1 times, word
825: rrccrr _a, _c_l Rotate right CL times, word
826: rreepp Repeat following string operation
827: rreeppee Find nonmatching bytes
828: rreeppnnee Repeat, not equal
829: rreeppnnzz Repeat, not equal
830: rreeppzz Repeat, equal
831: rreett Return from procedure
832: rroollbb _a, $_1 Rotate left, byte
833: rroollbb _a, _c_l Rotate left, byte
834: rrooll _a, $_1 Rotate left, word
835: rrooll _a, _c_l Rotate left, word
836: rroorrbb _a, $_1 Rotate right, byte
837: rroorrbb _a, _c_l Rotate right, byte
838: rroorr _a, $_1 Rotate right, word
839: rroorr _a, _c_l Rotate right, word
840: ssaahhff Store AH into flags
841: ssaallbb _a, $_1 Shift left, byte
842: ssaallbb _a, _c_l Shift left, byte
843: ssaall _a, $_1 Shift left, word
844: ssaall _a, _c_l Shift left, word
845: ssaarrbb _a, $_1 Shift right, byte
846: ssaarrbb _a, _c_l Shift right, byte
847: ssaarr _a, $_1 Shift right, word
848: ssaarr _a, _c_l Shift right, word
849: ssbbbbbb _r, _a Integer subtract with borrow, byte
850: ssbbbb _r, _a Integer subtract with borrow, word
851: ssbbbbbb _a, _r Integer subtract with borrow, byte
852: ssbbbb _a, _r Integer subtract with borrow, word
853: ssbbbbbb _a, $_e Integer subtract with borrow, byte
854:
855:
856: COHERENT Lexicon Page 13
857:
858:
859:
860:
861: as Command as
862:
863:
864:
865: ssbbbb _a, $_e Integer subtract with borrow, word
866: ssccaassbb Compare string data, byte
867: ssccaass Compare string data, word
868: sshhllbb _a, $_1 Shift left, byte
869: sshhllbb _a, _c_l Shift left, byte
870: sshhll _a, $_1 Shift left, word
871: sshhll _a, _c_l Shift left, word
872: sshhrrbb _a, $_1 Shift right, byte
873: sshhrrbb _a, _c_l Shift right, byte
874: sshhrr _a, $_1 Shift right, word
875: sshhrr _a, _c_l Shift right, word
876: ssttcc Set carry flag
877: ssttdd Set direction flag
878: ssttii Set interrupt enable flag
879: ssttoossbb Store string data, byte
880: ssttooss Store string data, byte or word
881: ssttoossww Store string data, word
882: ssuubbbb _r, _a Integer subtraction, byte
883: ssuubb _r, _a Integer subtraction, word
884: ssuubbbb _a, _r Integer subtraction, byte
885: ssuubb _a, _r Integer subtraction, word
886: ssuubbbb _a, $_e Integer subtraction, byte
887: ssuubb _a, $_e Integer subtraction, word
888: tteessttbb _r, _a Logical compare, byte
889: tteesstt _r, _a Logical compare, word
890: tteessttbb _a, _r Logical compare, byte
891: tteesstt _a, _r Logical compare, word
892: tteessttbb _a, $_e Logical compare, byte
893: tteesstt _a, $_e Logical compare, word
894: wwaaiitt Wait until BUSY pin is inactive
895: xxccaallll _d, _d Far call, immediate four-byte address
896: xxcchhggbb _r, _a Exchange memory, byte
897: xxcchhgg _r, _a Exchange memory, word
898: xxiiccaallll Far call, address at EA double word
899: xxiijjmmpp Jump far, address at memory double word
900: xxjjmmpp _d, _d Jump far, immediate four-byte address
901: xxllaatt Table look-up translation
902: xxoorrbb _r, _a Logical exclusive OR, byte
903: xxoorr _r, _a Logical exclusive OR, word
904: xxoorrbb _a, _r Logical exclusive OR, byte
905: xxoorr _a, _r Logical exclusive OR, word
906: xxoorrbb _a, $_e Logical exclusive OR, byte
907: xxoorr _a, $_e Logical exclusive OR, word
908: xxrreett Return, intersegment
909:
910: ***** 80286 Instructions *****
911:
912: The following instructions implement 80286-specific actions.
913: Programs that use them cannot be run on 8086-based machines.
914:
915: ppuusshhaa Push all general registers
916: ppooppaa Pop all general registers
917:
918: iinnssbb Input byte from port DX to ES:(DI)
919: iinnss Input word from port DX to ES:(DI)
920:
921:
922: COHERENT Lexicon Page 14
923:
924:
925:
926:
927: as Command as
928:
929:
930:
931: oouuttssbb Output byte from port DX from ES:(DI)
932: oouuttss Output word from port DX from ES:(DI)
933:
934: eenntteerr $_e, $_e Make stack frame for procedure
935: lleeaavvee Tear down stack frame for procedure
936:
937: bboouunndd _r, _e Check array index against bounds
938:
939: ssllddtt _a Store Local Descriptor Table Register
940: ssttrr _a Store Task Register
941: llllddtt _a Load Local Descriptor Table Register
942: llttrr _a Load Task Register
943: vveerrrr _a Verify a segment for reading
944: vveerrww _a Verify a segment for writing
945:
946: ssggddtt _m Store Global Descriptor Table register
947: ssiiddtt _m Store Interrupt Descriptor Table register
948: llggddtt _m Load Global Descriptor Table register
949: lliiddtt _m Load Interrupt Descriptor Table register
950: ssmmssww _a Store Machine Status Word
951: llmmssww _a Load Machine Status Word
952:
953: llaarr _r,_a Load access rights byte
954: llssll _r,_a Load segment limit
955:
956: ccllttss Clear Task Switched Flag
957: aarrppll Adjust RPL field of Selector
958:
959: ppuusshh $_e Push sign extended byte
960: Also the $_1 forms become $_e on rol, rolb, ror, rorb, sal, salb,
961: shrb, shr, and shrb. This is because 8086 task of shifting and
962: rotating by an immediate value could only take an immediate value
963: of 1; however, on the 80286 the immediate value may be up to 31.
964:
965: ***** i8087 Op Codes *****
966:
967: The assembler can also generate object files for use with the
968: i8087 mathematics co-processor. The following listing presents
969: the assembly language op codes for this feature. sstt00 indicates
970: floating point register 0 and sstt11 indicates any floating point
971: register but 0; dd is the same as in the above listing.
972:
973:
974: _d Direct address
975: _s_t_0Floating point register 0
976: _s_t_1Any floating point register _e_x_c_e_p_t 0
977:
978:
979: The following lists the i8087 instructions:
980: ffaabbss Absolute value
981: ffaadddd _s_t_0, _s_t_1Add real
982: ffaadddd _s_t_1, _s_t_0Add real
983: ffffaadddd _d Add real, float
984: ffddaadddd _d Add real, double
985: ffaaddddpp Add real and pop
986:
987:
988: COHERENT Lexicon Page 15
989:
990:
991:
992:
993: as Command as
994:
995:
996:
997: ffaaddddpp _s_t, _s_t_0 Add real and pop
998: ffbblldd _d Load packed decimal (BCD)
999: ffbbssttpp _d Store packed decimal (BCD) and pop
1000: ffcchhss Change sign
1001: ffcclleexx Clear exception
1002: ffnncclleexx Clear exception
1003: ffccoomm Compare real
1004: ffffccoomm _d Compare real, float
1005: ffddccoomm _d Compare real, double
1006: ffccoommpp Compare real and pop
1007: ffccoommpp st1 Compare real and pop
1008: ffffccoommpp _d Compare real and pop, float
1009: ffddccoommpp _d Compare real and pop, double
1010: ffccoommpppp Compare real and pop twice
1011: ffddeeccssttpp Decrement stack pointer
1012: ffddiissii Disable interrupts
1013: ffnnddiissii Disable interrupts, no operands
1014: ffddiivv _s_t_0, _s_t_1Divide real
1015: ffddiivv _s_t_1, _s_t_0Divide real
1016: ffffddiivv _d Divide real, float
1017: ffddddiivv _d Divide real, double
1018: ffddiivvpp Divide real and pop
1019: ffddiivvpp st1 Divide real and pop
1020: ffddiivvrr _s_t_0, _s_t_1Divide real reversed
1021: ffddiivvrr _s_t_1, _s_t_0Divide real reversed
1022: ffffddiivvrr _d Divide real reversed, float
1023: ffddddiivvrr _d Divide real reversed, double
1024: ffddiivvrrpp Divide real reversed and pop
1025: ffddiivvrrpp _s_t_1 Divide real reversed and pop
1026: ffeennii Enable interrupts
1027: ffnneennii Enable interrupts, no operands
1028: ffffrreeee _s_t_1 Free register
1029: ffiiaadddd _d Integer add
1030: ffllaadddd _d Integer add, long
1031: ffiiccoomm _d Integer compare
1032: ffllccoomm _d Integer compare, long
1033: ffiiccoommpp _d Integer compare and pop
1034: ffllccoommpp _d Integer compare and pop, long
1035: ffiiddiivv _d Integer divide
1036: ffllddiivv _d Integer divide, long
1037: ffiiddiivvrr _d Integer divide reversed
1038: ffllddiivvrr _d Integer divide, long reversed
1039: ffiilldd _d Integer load
1040: fflllldd _d Integer load, long
1041: ffqqlldd _d Integer load, quad
1042: ffiimmuull _d Integer multiply
1043: ffllmmuull _d Integer multiply, long
1044: ffiinnccssttpp Increment stack pointer
1045: ffiinniitt Initialize processor
1046: ffnniinniitt Initialize processor
1047: ffiisstt _d Integer store
1048: ffllsstt _d Integer store, long
1049: ffiissttpp _d Integer store and pop
1050: ffllssttpp _d Integer store and pop, long
1051: ffqqssttpp _d Integer store and pop, quad
1052:
1053:
1054: COHERENT Lexicon Page 16
1055:
1056:
1057:
1058:
1059: as Command as
1060:
1061:
1062:
1063: ffiissuubb _d Integer subtract
1064: ffllssuubb _d Integer subtract, long
1065: ffiissuubbrr _d Integer subtract reversed
1066: ffllssuubbrr _d Integer subtract reversed, long
1067: fflldd _s_t_1 Load real
1068: fffflldd _d Load real, float
1069: ffddlldd _d Load real, double
1070: ffttlldd _d Load real, temp
1071: ffllddccww _d Load control word
1072: ffllddeennvv _d Load environment
1073: ffllddllgg22 Load log(10)2
1074: ffllddllnn22 Load log(e)2
1075: ffllddll22ee Load log(2)e
1076: ffllddll22tt Load log(2)10
1077: ffllddppii Load pi
1078: ffllddzz Load +0.0
1079: fflldd11 Load +1.0
1080: ffmmuull Multiply real
1081: ffmmuull _s_t_0, _s_t_1Multiply real
1082: ffffmmuull _s_t_1, _s_t_0Multiply real, float
1083: ffddmmuull _d Multiply real, double
1084: ffmmuullpp _d Multiply real and pop
1085: ffnnoopp st1 No operation
1086: ffppaattaann Partial arctangent
1087: ffpprreemm Partial remainder
1088: ffppttaann Partial tangent
1089: ffrrnnddiinntt Round to integer
1090: ffrrssttoorr _d Restore saved state
1091: ffssaavvee _d Save state
1092: ffnnssaavvee _d Save state
1093: ffssccaallee Scale
1094: ffsseettppmm Set protected mode
1095: ffssqqrrtt Square root
1096: ffsstt _s_t_1 Store real
1097: ffffsstt _d Store real, float
1098: ffddsstt _d Store real, double
1099: ffssttccww _d Store control word
1100: ffnnssttccww _d Store control word
1101: ffsstteennvv _d Store environment
1102: ffnnsstteennvv _d Store environment
1103: ffssttpp _s_t_1 Store real and pop
1104: ffffssttpp _d Store real and pop, float
1105: ffddssttpp _d Store real and pop, double
1106: ffttssttpp _d Store real and pop, temp
1107: ffssttssww _d Store status word
1108: ffnnssttssww _d Store status word
1109: ffssuubb _s_t_0, _s_t_1Subtract real
1110: ffssuubb _s_t_1, _s_t_0Subtract real
1111: ffffssuubb _d Subtract real, float
1112: ffddssuubb _d Subtract real, double
1113: ffssuubbpp Subtract real and pop
1114: ffssuubbpp _s_t_1 Subtract real and pop
1115: ffssuubbrr _d Subtract real reversed
1116: ffffssuubbrr _d Subtract real reversed, float
1117: ffddssuubbrr _d Subtract real reversed, double
1118:
1119:
1120: COHERENT Lexicon Page 17
1121:
1122:
1123:
1124:
1125: as Command as
1126:
1127:
1128:
1129: ffssuubbrrpp Subtract real reversed and pop
1130: ffssuubbrrpp _s_t_1 Subtract real reversed and pop
1131: ffttsstt Test stack top against +0.0
1132: ffwwaaiitt Wait while 8087 is busy
1133: ffxxaamm Examine stack top
1134: ffxxcchh _s_t_1 Exchange registers
1135: ffxxcchh Exchange registers
1136: ffxxttrraacctt Extract exponent and significance
1137: ffyyll22xx Y*log(2)X
1138: ffyyll22xxpp11 Y*log(2)(X+1)
1139:
1140: ***** C Compiler Conventions *****
1141:
1142: as is often used to write small functions that perform tasks not
1143: easily or efficiently done in C. Such functions are intended to
1144: be called from a C program. As long as the assembly language
1145: source code follows compiler conventions, the assembler routine
1146: will be fully compatible with C functions. These conventions are
1147: (1) the names of external variables and (2) calling functions.
1148:
1149: ***** Naming Conventions *****
1150:
1151: The C compiler appends an underline character `_' to the end of
1152: every external declared in a C source file. When referring to
1153: any external variable or function declared in a C source file,
1154: append an underscore to the name. In a similar manner, when
1155: defining a function or variable in an assembly language source
1156: file that is to be accessed from a C source file, append an un-
1157: derline character.
1158:
1159: ***** Function-Calling Conventions *****
1160:
1161: Function-calling conventions deal with how arguments are passed
1162: to functions, how values are returned, and which registers are
1163: used for special purposes and must be protected.
1164:
1165: ***** Arguments *****
1166:
1167: Function arguments are passed on the stack. They are pushed by
1168: the calling function, which also removes them when the called
1169: function returns. Looking at the declaration of the function,
1170: the order in which they are pushed onto the stack is from right
1171: to left; that is, the C compiler pushes the argument list in
1172: reverse order of declaration. The instruction call to jump to
1173: the function also pushes the return address, so that when the
1174: called routine gains control the first argument is found at of-
1175: fset 2 from the stack pointer.
1176:
1177: Integer and pointer arguments are word size, and are simply
1178: pushed with a push instruction. Characters, although byte size,
1179: are not passed as bytes. The C language requires that char
1180: variables be promoted to the type int before being passed. The
1181: promotion is signed or unsigned, depending on the type of the
1182: char variable. lloonnggs are pushed one word at a time; the higher-
1183: address word is pushed first. This ensures that the words of the
1184:
1185:
1186: COHERENT Lexicon Page 18
1187:
1188:
1189:
1190:
1191: as Command as
1192:
1193:
1194:
1195: long are in the correct order on the stack, because the stack
1196: grows toward low-addressed memory.
1197:
1198: Passing ffllooaatts, ddoouubbllees, or structure arguments is more involved.
1199: C requires ffllooaatts to be promoted to and passed as ddoouubbllees, so
1200: this conversion must be performed first. ddoouubbllees and structures
1201: are passed so that as they sit on the stack, all bytes are in the
1202: correct order; this is analogous to the passing of lloonnggs. This
1203: means, for example, that ddoouubbllees may be pushed with four push
1204: word instructions, beginning with the highest addressed word in
1205: the 64-bit double, and ending with the lowest addressed word.
1206:
1207: If in doubt about how to apply any of this, try writing a simple
1208: C program that uses what you need, and compile it with the -vasm
1209: option to the cc command. This produces an assembly-language
1210: version of the C program, which can be studied to see exactly
1211: what the compiler does, and mimicked to good effect.
1212:
1213: ***** Return Values *****
1214:
1215:
1216: Functions return values in various registers according to their
1217: type. iinntts and pointers are returned in the ax register. cchhaarrs
1218: are returned by first promoting them to iinntts and returning the
1219: result in the ax register; effectively, this means that cchhaarrs are
1220: returned in the al register. lloonnggs are returned in the dx:ax
1221: register pair, with the most significant word (also the high-ad-
1222: dress word) in the dx register, and the least significant word in
1223: the ax register.
1224:
1225: ffllooaatts, ddoouubbllees, and structures are returned in a more complex
1226: fashion. C requires ffllooaatts be returned as ddoouubbllees, so they are
1227: converted. ddoouubbllees are returned in a special eight-byte array
1228: named _ffppaacc (of course, in assembly language the name is _ffppaacc_).
1229: This array is defined by the compiler. In the event that a func-
1230: tion returns a structure, the contents of the structure are saved
1231: in memory, and the function returns a pointer to that structure
1232: in the ax register. The calling function then moves the bytes
1233: into the actual destination.
1234:
1235: Again, if in doubt about how to do this in assembly language, try
1236: compiling a function with assembly language output to see how the
1237: compiler does it.
1238:
1239: ***** Important Registers *****
1240:
1241: Every function must preserve the value of the bp register, which
1242: is the caller's stack frame pointer. Also, the compiler uses the
1243: si and di registers for register variables, so they must be
1244: preserved.
1245:
1246: ***** Example of an Assembly Language Program *****
1247:
1248: The following assembly language file, strchar.s defines a func-
1249: tion strchar that returns the number of occurrences of a charac-
1250:
1251:
1252: COHERENT Lexicon Page 19
1253:
1254:
1255:
1256:
1257: as Command as
1258:
1259:
1260:
1261: ter in a string.
1262:
1263:
1264: FILE: strchar.s
1265:
1266: /
1267: /
1268: / Count and return the occurrences
1269: / of a character in a string.
1270: /
1271: / int
1272: / strchar(s, c)
1273: / char *s;
1274: / int c;
1275: /
1276: /
1277:
1278:
1279:
1280: .globl strchar_ / Make the name known externally.
1281:
1282: strchar_:
1283: push si / Standard C function
1284: push di / linkage. Save the
1285: push bp / si, di, and bp registers
1286: mov bp, sp / and set up new frame pointer.
1287:
1288:
1289:
1290: mov si, 8(bp) / String ptr -> si.
1291: mov bx, 10(bp) / Char -> bx (actually bl).
1292: sub ax, ax / Clear ax (count register).
1293: sub cx, cx / Clear cx.
1294:
1295:
1296:
1297: 0: movb cl, (si) / Get character from string.
1298: jcxz 2f / End of string?
1299: cmpb bl, cl / No. Do chars match?
1300: jnz 1f / No.
1301: inc ax / Yes. Increment count.
1302:
1303:
1304:
1305: 1: inc si / Bump string pointer
1306: jmp 0b / and loop again.
1307:
1308:
1309:
1310: 2: pop bp / Standard C return
1311: pop di / linkage. Restore
1312: pop si / saved registers and
1313: ret / go home.
1314:
1315:
1316:
1317:
1318: COHERENT Lexicon Page 20
1319:
1320:
1321:
1322:
1323: as Command as
1324:
1325:
1326:
1327:
1328: The following C program, main.c uses strchar The assembly lan-
1329: guage listing that follows, main.s was produced from main.c by
1330: the -vasm option in cc. The listing has been edited, and com-
1331: ments added, to illustrate what is happening.
1332:
1333:
1334: FILE: main.c
1335:
1336: main()
1337: {
1338: int n;
1339: n = strchar("aardvark", 'a');
1340: }
1341:
1342:
1343:
1344: FILE: main.s
1345:
1346: .shri / ``code'' program section.
1347:
1348: .globl main_
1349:
1350:
1351:
1352: main_:
1353:
1354: .strn / ``string'' program section.
1355:
1356:
1357:
1358: L2: .byte 0x61 / This is the string
1359: .byte 0x61 / ``aardvark''
1360: .byte 0x72
1361: .byte 0x64
1362: .byte 0x76
1363: .byte 0x61
1364: .byte 0x72
1365: .byte 0x6B
1366: .byte 0x00
1367:
1368:
1369:
1370: .shri / Back to ``code''
1371:
1372: push si / Standard C function
1373: push di / linkage. Save registers,
1374: push bp / set up new frame pointer (bp),
1375: mov bp, sp / and make room on stack
1376: sub sp, $0x02 / for the auto int, ``n''
1377:
1378:
1379:
1380:
1381:
1382:
1383:
1384: COHERENT Lexicon Page 21
1385:
1386:
1387:
1388:
1389: as Command as
1390:
1391:
1392:
1393: mov ax, $0x61 / Push the
1394: push ax / character `a'.
1395: mov ax, $L2 / Push the address
1396: push ax / of the string ``aardvark''
1397: call strchar_ / Function call.
1398: add sp, $0x04 / Remove args from stack.
1399: mov -0x02(bp), ax / Assign result to auto `n'.
1400:
1401:
1402:
1403: mov sp, bp / Standard C return
1404: pop bp / linkage. Adjust stack
1405: pop di / pointer, then restore
1406: pop si / registers and
1407: ret / go home.
1408:
1409:
1410: ***** Diagnostics *****
1411:
1412: All errors detected by the assembler are reported on the screen
1413: as an error message that is tagged with a line number. If a sym-
1414: bol is associated with the error message (for example, if a sym-
1415: bol is undefined), then the symbol's name is also given. If more
1416: than one input file appears on the command line, error messages
1417: are tagged with the name of the source file.
1418:
1419: If a listing is generated, errors are reported on the listing in
1420: the same format, with the error flags at the left margin. The
1421: total number of errors is displayed on the screen at the end of
1422: the assembly.
1423:
1424: For a full listing of aass error messages, see the tutorial for the
1425: C compiler, which appears earlier in this manual.
1426:
1427: ***** See Also *****
1428:
1429: cc, commands
1430:
1431:
1432:
1433:
1434:
1435:
1436:
1437:
1438:
1439:
1440:
1441:
1442:
1443:
1444:
1445:
1446:
1447:
1448:
1449:
1450: COHERENT Lexicon Page 22
1451:
1452:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.