home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / primer2.zip / PRIMER.DOC
Text File  |  1985-08-15  |  43KB  |  1,433 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.                 An Assembly Language Primer
  18.  
  19.                  (C) 1983 by David Whitman
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.                                                                        1
  73.  
  74.               TABLE OF CONTENTS
  75.  
  76.  
  77. Introduction.......................................2
  78.  
  79. The Computer As A Bit Pattern Manipulator..........2
  80.  
  81. Digression: A Notation System for Bit Patterns.....4
  82.  
  83. Addressing Memory..................................6
  84.  
  85. The Contents of Memory: Data and Programs..........7
  86.  
  87. The Dawn of Assembly Language......................8
  88.  
  89. The 8088...........................................9
  90.  
  91. Assembly Language Syntax..........................12
  92.  
  93. The Stack.........................................14
  94.  
  95. Software Interrupts...............................15
  96.  
  97. Pseudo-Operations.................................17
  98.  
  99. Tutorial..........................................18
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.                                                                        2
  139.  
  140. INTRODUCTION
  141.  
  142. Many people requesting CHASM have indicated that they are
  143. interested in *learning* assembly language.  They are beginners,
  144. and have little idea just where to start.  This primer is
  145. directed to those users.  Experianced users will probably find
  146. little here that they do not already know.
  147.  
  148. Being a primer, this text will not teach you everything there is
  149. to know about assembly language programming.  It's purpose is to
  150. give you some of the vocabulary and general ideas which will help
  151. you on your way.
  152.  
  153. I must make a small caveat: I consider myself a relative beginner
  154. in assembly language programming.  A big part of the reason for
  155. writing CHASM was to try and learn this branch of programming
  156. from the inside out.  I think I've learned quite a bit, but it's
  157. quite possible that some of the ideas I relate here may have some
  158. small, or even large, flaws in them.  Nonetheless, I have
  159. produced a number of working assembly language programs by
  160. following the ideas presented here.
  161.  
  162. THE COMPUTER AS A BIT PATTERN MANIPULATOR.
  163.  
  164. We all have some conception about what a computer does.  On one
  165. level, it may be thought of as a machine which can execute BASIC
  166. programs.  Another idea is that the computer is a number
  167. crunching device.  As I write this primer, I'm using my computer
  168. as a word processor.
  169.  
  170. I'd like to introduce a more general concept of just what sort of
  171. machine a computer is: a bit pattern manipulator.
  172.  
  173. I'm certain that everyone has been introduced to the idea of a
  174. *bit*.  (Note: Throughout this primer, a word enclosed in
  175. *asterisks* is to be read as if it were in italics.)  A bit has
  176. two states: on and off, typically represented with the symbols
  177. "1"  and "0".  In this context, DON'T think of 1 and 0 as
  178. numbers.  They are merely convenient shorthand labels for the
  179. state of a bit.
  180.  
  181. The memory of your computer consists of a huge collection of
  182. bits, each of which could be in either the 1 or 0 (on or off)
  183. state.
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.                                                                        3
  205.  
  206.  
  207. At the heart of your computer is a microprocessor chip, named the
  208. 8088 by Intel, who makes the chip.  What this chip can do is
  209. manipulate the bits which make up the memory.  The 8088 likes to
  210. handle bits in chunks, and so we'll introduce special names for
  211. the two sizes of bit chunks the 8088 is most happy with.  A
  212. *byte* will refer to a collection of eight bits.  A *word*
  213. consists of two bytes, or equivalently, sixteen bits.
  214.  
  215. A collection of bits holds a pattern, determined by the state of
  216. it's individual bits.  Here are some typical byte long patterns:
  217.  
  218. 10101010         11111111         00001111
  219.  
  220. If you've had a course in probability, it's quite easy to work
  221. out that there are 256 possible patterns that a byte could hold.
  222. Similarly, a word can hold 65,536 different patterns.
  223.  
  224. All right, now for the single most important idea in assembly
  225. language programming.  Are you sitting down?  These bit patterns
  226. can be used to represent other sets of things, by mapping each
  227. pattern onto a member of the other set.  Doesn't sound like much,
  228. but IBM has made *BILLIONS* off this idea.
  229.  
  230. For example, by mapping the patterns a word can hold onto the set
  231. of integers, you can represent either the numbers from 0 to 65535
  232. or -32768 to 32767, depending on the exact mapping you use.  You
  233. might recognize these number ranges as the range of possible line
  234. numbers, and the possible values of an integer variable, in BASIC
  235. programs.  This explains these somewhat arbitrary seeming limits:
  236. BASIC uses words of memory to hold line numbers and integer
  237. variables.
  238.  
  239. As another example, you could map the patterns a byte can hold
  240. onto a series of arbitrarily chosen little pictures which might
  241. be displayed on a video screen.  If you look in appendix G of
  242. your BASIC manual, you'll notice that there are *exactly* 256
  243. differant characters that can be displayed on your screen.  Your
  244. computer uses a byte of memory to tell it what character to
  245. display at each location of the video screen.
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.                                                                        4
  271.  
  272. Without getting too far ahead of myself, I'll just casually
  273. mention that there are about 256 fundamental operations that the
  274. 8088 microprocessor chip can carry out.  This suggests another
  275. mapping which we'll discuss in more detail later.
  276.  
  277. The point of this discussion is that we can use bit patterns to
  278. represent anything we want, and by manipulating the patterns in
  279. differant ways, we can produce results which have significance in
  280. terms of what we're choosing to represent.
  281.  
  282. DIGRESSION: A NOTATION SYSTEM FOR BIT PATTERNS
  283.  
  284. Because of their importance, it would be nice to have a
  285. convenient way to represent the various bit patterns we'll be
  286. talking about.  We already have one way, by listing the states of
  287. the individual bits as a series of 1's and 0's.  This system is
  288. somewhat clumsy, and error prone.  Are the following word
  289. patterns identical or different?
  290.  
  291. 1111111011111111                         1111111101111111
  292.  
  293. You probably had trouble telling them apart.  It's easier to tell
  294. that they're different by breaking them down into more managable
  295. pieces, and comparing the pieces.  Here are the same two patterns
  296. broken down into four bit chunks:
  297.  
  298. 1111 1110 1111 1111                  1111 1111 0111 1111
  299.  
  300. Some clown has given the name *nybble* to a chunk of 4 bits,
  301. presumably because 4 bits are half a byte.  A nybble is fairly
  302. easy to handle.  There are only 16 possible nybble long patterns,
  303. and most people can distinguish between the patterns quite
  304. easily.
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.                                                                        5
  337.  
  338. Each nybble pattern has been given a unique symbol agreed upon by
  339. computer scientists.  The first 10 patterns were given symbols
  340. "0" through "9", and when they ran out of digit style symbols,
  341. they used the letters "A" through "F" for the last six patterns.
  342. Below is the "nybble pattern code":
  343.  
  344. 0000 = 0    0001 = 1    0010 = 2    0011 = 3
  345.  
  346. 0100 = 4    0101 = 5    0110 = 6    0111 = 7
  347.  
  348. 1000 = 8    1001 = 9    1010 = A    1011 = B
  349.  
  350. 1100 = C    1101 = D    1110 = E    1111 = F
  351.  
  352. Using the nybble code, we can represent the two similar word
  353. patterns given above, with the following more managable shorthand
  354. versions:
  355.  
  356.                FEFF       FF7F
  357.  
  358. Of course, the assignment of the symbols for the various nybble
  359. patterns was not so arbitrary as I've tried to make it appear.  A
  360. perceptive reader who has been exposed to binary numbers will
  361. have noticed an underlying system to the assignments.  If the 1's
  362. and 0's of the patterns are interpreted as actual *numbers*,
  363. rather than mere symbols for bit states, the first 10 patterns
  364. correspond to binary numbers whose decimal representation is the
  365. symbol assigned to the pattern.  The last six patterns receive the
  366. symbols "A" through "F", and taken together, the symbols 0
  367. through F constitute the digits of the *hexadecimal* number
  368. system.  Thus, the symbols assigned to the different nybble
  369. patterns were born out of historical prejudice in thinking of
  370. the computer as strictly a number handling machine.  Although
  371. this is an important interpretation of these symbols, for the
  372. time being it's enough to merely think of them as a shorthand way
  373. to write down bit patterns.
  374.  
  375. Because some nybble patterns can look just like a number, it's
  376. often necessary to somehow indicate that we're talking about a
  377. pattern.  In BASIC, you do this by adding the characters &H to
  378. the beginning of the pattern: &H1234.  A more common convention
  379. is to just add the letter H to the end of the pattern: 1234H.  In
  380. both conventions, the H is referring to hexadecimal.
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.                                                                        6
  403.  
  404. Eventually you'll want to learn about using the hexadecimal
  405. number system, since it is an important way to use bit patterns.
  406. I'm not going to discuss it in this primer, because a number of
  407. books have much better treatments of this topic than I could
  408. produce.  Consider this an advanced topic you'll want to fill in
  409. later.
  410.  
  411. ADDRESSING MEMORY
  412.  
  413. As stated before, the 8088 chip inside your computer can
  414. manipulate the bit patterns which make up the computer's memory.
  415. Some of the possible manipulations are copying patterns from one
  416. place to another, turning on or turning off certain bits, or
  417. interpreting the patterns as numbers and performing arithmetic
  418. operations on them.  To perform any of these actions, the 8088
  419. has to know what part of memory is to be worked on.  A specific
  420. location in memory is identified by it's *address*.
  421.  
  422. An address is a pointer into memory.  Each address points to the
  423. beginning of a byte long chunk of memory.  The 8088 has the
  424. capability to distinguish 1,048,576 differant bytes of memory.
  425.  
  426. By this point, it probably comes as no suprise to hear that
  427. addresses are represented as patterns of bits.  It takes 20 bits
  428. to get a total of 1,048,576 differant patterns, and thus an
  429. address may be written down as a series of 5 nybble codes.  For
  430. example, DOS stores a pattern which encodes information about
  431. what equipment is installed on your IBM PC in the word which
  432. begins at location 00410.  Interpreting the address as a hex
  433. number, the second byte of this word has an address 1 greater
  434. than 00410, or 00411.
  435.  
  436. The 8088 isn't very happy handling 20 bits at a time.  The
  437. biggest chunk that's convenient for it to use is a 16 bit word.
  438. The 8088 actually calculates 20 bit addresses as the combination
  439. of two words, a segment word and an offset word.  The combination
  440. process involves interpreting the two patterns as hexadecimal
  441. numbers and adding them.  The way that two 16 bit patterns can be
  442. combined to give one 20 bit pattern is that the two patterns are
  443. added out of alignment by one nybble:
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.                                                                        7
  469.  
  470.     0040      4 nybble segment
  471.      0010     4 nybble offset
  472.    --------
  473.     00410     5 nybble address
  474.  
  475. Because of this mechanism for calculating addresses, they will
  476. often be written down in what may be called segment:offset form.
  477. Thus, the address in above calculation could be written:
  478.  
  479. 0040:0010
  480.  
  481. MEMORY CONTERNS: DATA AND PROGRAMS
  482.  
  483. The contents of memory may be broken down into two broad classes.
  484. The first is *data*, just raw patterns of bits for the 8088 to
  485. work on.  The significance of the patterns is determined by what
  486. the computer is being used for at any given time.
  487.  
  488. The second class of memory contents are *instructions*.  The 8088
  489. can look at memory and interpret a pattern it sees there as
  490. specifying one of the 200 some fundamental operations it knows how
  491. to do.  This mapping of patterns onto operations is called the
  492. *machine language* of the 8088.  A machine language *program*
  493. consists of a series of patterns located in consequtive memory
  494. locations, whose corresponding operations perform some useful
  495. process.
  496.  
  497. Note that there is no way for the 8088 to know whether a given
  498. pattern is meant to be an instruction, or a piece of data to
  499. operate on.  It is quite possible for the chip to accidentally
  500. begin reading what was intended to be data, and interpret it as a
  501. program.  Some pretty bizarre things can occur when this happens.
  502. In assembly language programming circles, this is known as
  503. "crashing the system".
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.                                                                        8
  535.  
  536. THE DAWN OF ASSEMBLY LANGUAGE
  537.  
  538. Unless you happen to be an 8088 chip, the patterns which make up
  539. a machine language program can be pretty incomprehensible.  For
  540. example, the pattern which tells the 8088 to flip all the bits in
  541. the byte at address 5555 is:
  542.  
  543. F6 16 55 55
  544.  
  545. which is not very informative, although you can see the 5555
  546. address in there.  In ancient history, the old wood-burning and
  547. vacuum tube computers were programmed by laboriously figuring out
  548. bit patterns which represented the series of instructions
  549. desired.  Needless to say, this technique was incredibly tedious,
  550. and very prone to making errors.  It finally occured to these
  551. ancestral programmers that they could give the task of figuring
  552. out the proper patterns to the computer itself, and assembly
  553. language programming was born.
  554.  
  555. Assembly language represents each of the many operations that the
  556. computer can do with a *mnemonic*, a short, easy to remember
  557. series of letters.  For example, in boolean algebra, the logical
  558. operation which inverts the state of a bit is called "not", and
  559. hence the assembly language equivalent of the preceding machine
  560. language pattern is:
  561.  
  562.     NOTB [5555]
  563.  
  564. The brackets around the 5555 roughly mean "the memory location
  565. addressed by".  The "B" at the end of "NOTB" indicates that we
  566. want to operate on a byte of memory, not a word.
  567.  
  568. Unfortunately, the 8088 can't make head nor tail of the string of
  569. characters "NOTB".  What's needed is a special program to run on
  570. the 8088 which converts the string "NOTB" into the pattern F6 16.
  571. This program is called an assembler.  A good analogy is that an
  572. assembler program is like a meat grinder which takes in assembly
  573. language and gives out machine language.
  574.  
  575. Typically, an assembler reads a file of assembly language and
  576. translates it one line at a time, outputing a file of machine
  577. language.  Often times the input file is called the *source file*
  578. and the output file is called the *object file*.  The machine
  579. language patterns produced are called the *object code*.
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.                                                                        9
  601.  
  602.  
  603. Also produced during the assembly process is a *listing*, which
  604. summarizes the results of the assembly process.  The listing
  605. shows each line from the source file, along with the shorthand
  606. "nybble code" representation of the object code produced.  In the
  607. event that the assembler was unable to understand any of the source
  608. lines, it inserts error messages in the listing, pointing out the
  609. problem.
  610.  
  611. The primeval assembly language programmers had to write their
  612. assembler programs in machine language, because they had no other
  613. choice.  Not being a masochist, I wrote CHASM in BASIC.  When you
  614. think about it, there's a sort of circular logic in action here.
  615. Some programmers at Microsoft wrote the BASIC interpreter in
  616. assembly language, and I used BASIC to write an assembler.
  617. Someday, I hope to use the present version of CHASM to
  618. produce a machine language version, which will run about a
  619. hundred times faster, and at the same time bring this crazy
  620. process full circle.
  621.  
  622. THE 8088
  623.  
  624. The preceding discussions have (I hope) given you some very
  625. general background, a world view if you will, about assembly and
  626. machine language programming.  At this point, I'd like to get
  627. into a little more detail, beginning by examining the internal
  628. structure of the 8088 microprocessor, from the programmer's point
  629. of view.  This discussion is a condensation of information which
  630. I obtained from "The 8086 Book" which was written by Russell
  631. Rector and George Alexy, and published by Osborne/McGraw-Hill.
  632. Once you've digested this, I'd recomend going to The 8086 Book
  633. for a deeper treatment.  To use the CHASM assembler, you're going
  634. to need The 8086 Book anyway, to tell you the different 8088
  635. instructions and their mnemonics.
  636.  
  637. Inside the 8088 are a number of *registers* each of which can
  638. hold a 16 bit pattern.  In assembly language, each of the
  639. registers has a two letter mnemonic name.  There are 14
  640. registers, and their mnemonics are:
  641.  
  642. AX BX CX DX     SP BP    SI DI     CS DS SS ES    PC ST
  643.  
  644. Each of the registers are a little different and have different
  645. intended uses, but they can be grouped into some broad classes.
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.                                                                        10
  667.  
  668.  
  669. The *general purpose* registers (AX BX CX DX) are just that.
  670. These are registers which hold patterns pulled in from memory
  671. which are to be worked on within the 8088.  You can use these
  672. registers for just about anything you want.
  673.  
  674. Each of the general purpose registers can be broken down into two
  675. 8 bit registers, which have names of their own.  Thus, the CX
  676. register is broken down into the CH and CL registers.  The "H"
  677. and "L" stand for high and low respectively.  Each general
  678. purpose register breaks down into a high/low pair.
  679.  
  680. The AX register, and it's 8 bit low half, the AL register, are
  681. somewhat special.  Mainly for historical reasons, these registers
  682. are referred to as the 16 bit and 8 bit *accumulators*.  Some
  683. operations of the 8088 can only be carried out on the contents of
  684. the accumulators, and many others are faster when used in
  685. conjunction with these registers.
  686.  
  687. Another group of registers are the *segment* registers (CS DS SS
  688. ES).  These registers hold segment values for use in calculating
  689. memory addresses.  The CS, or code segment register, is used
  690. every  time the 8088 accesses memory to read an instruction
  691. pattern.  The  DS, or data segment register, is used for bringing
  692. data patterns in.  The SS register is used to access the stack
  693. (more about the stack later).  The ES is the extra segment
  694. register.  A very few special instructions use the ES register to
  695. access memory, plus you can overide use of the DS register and
  696. substitute the ES register, if you need to maintain two separate
  697. data areas.
  698.  
  699. The *pointer* (SP BP) and *index* (DI SI) registers are used to
  700. provide indirect addressing, which is an very powerful technique
  701. for accessing memory.  Indirect addressing is beyond the scope of
  702. this little primer, but is discussed in The 8086 Book.  The SP
  703. register is used to implement a stack in memory. (again, more
  704. about the stack later)  Besides their special function, the BP,
  705. DI and SI registers can be used as additional general purpose
  706. registers.  Although it's physically possible to directly
  707. manipulate the value in the SP register, it's best to leave it
  708. alone, since you could wipe out the stack.
  709.  
  710. Finally, there are two registers which are relatively
  711. inaccessable to direct manipulation.  The first is the *program
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.                                                                        11
  733.  
  734. counter*, PC.  This register always contains the offset part of
  735. the address of the next instruction to be executed.  Although
  736. you're not allowed to just move values into this register, you
  737. *can* indirectly affect it's contents, and hence the next
  738. instruction to be executed, using operations which are equivalent
  739. to BASIC's GOTO and GOSUB instructions.  Occasionally, you will
  740. see the PC referred to as the *IP*, which stands for instruction
  741. pointer.
  742.  
  743. The last register is also relatively inaccessable.  This is the
  744. *status* register, ST.  This one has a *two* alternate names, so
  745. watch for FL (flag register) and PSW (program status word).  The
  746. latter is somewhat steeped in history, since this was the name
  747. given to a special location in memory which served a similar
  748. function on the antique IBM 360 mainframe.
  749.  
  750. The status register consists of a series of one bit *flags* which
  751. can affect how the 8088 works.  There are special instructions
  752. which allow you to set or clear each of these flags.  In
  753. addition, many instructions affect the state of the flags,
  754. depending on the outcome of the instruction.  For example, one of
  755. the bits of the status register is called the Zero flag.  Any
  756. operation which ends up generating a bit pattern of all 0's
  757. automatically sets the Zero flag on.
  758.  
  759. Setting the flags doesn't seem to do much, until you know that
  760. there a whole set of conditional branching instructions which
  761. cause the equivalent to a BASIC GOTO if the particular µmπg
  762. pattern they look for is set.  In assembly language, the only way
  763. to make a decision and branch accordingly is via this flag testing
  764. mechanism.
  765.  
  766. Although some instructions implicitly affect the flags, there are
  767. a series of instructions whose *only* effect is to set the flags,
  768. based on some test or comparision.  It's very common to see one
  769. of these comparision operations used to set the flags just before
  770. a conditional branch.  Taken together, the two instructions are
  771. exactly equivalent to BASIC's:
  772.  
  773. IF (comparision) THEN GOTO (linenumber)
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.                                                                        12
  799.  
  800.  
  801. ASSEMBLY LANGUAGE SYNTAX
  802.  
  803. In general, each line of an assembly language program translates
  804. to a set of patterns which specify one fundamental operation for
  805. the 8088 to carry out.
  806.  
  807. Each line may consist of one or more of the following parts:
  808.  
  809. First, a label, which is just a marker for the assembler to use.
  810. If you want to branch to an instruction from some other part of
  811. the program, you put a label on the instruction.  When you want to
  812. branch, you refer to the label.  In general, the label can be any
  813. string of characters you want.  A good practice is to use a name
  814. which reminds you what that particular part of the program does.
  815. CHASM will assume that any string of characters which starts in
  816. the first column of a line is intended to be a label.
  817.  
  818. After the label, or if the text of the line starts to the right
  819. of the first column, at the beginning of the text, comes an
  820. instruction mnemonic.  This specifies the operation that the line
  821. is asking for.  For a list of the 200-odd mnemonics, along with
  822. the instructions they stand for, see The 8086 Book.
  823.  
  824. Most of the 8088 instructions require that you specify one or
  825. more *operands*.  The operands are what the operation is to work
  826. on, and are listed after the instruction mnemonic.
  827.  
  828. There are a number of possible operands.  Probably the most common
  829. are registers, specified by their two letter mnemonics.
  830.  
  831. Another operand type is *immediate data*, a pattern of bits to be
  832. put somewhere or compared or combined with some other pattern.
  833. Generally immediate data is specified by it's nybble code
  834. representation, marked as such by following it with the letter
  835. "H".  Some assemblers allow alternate ways to specify immediate
  836. data which emphasize the pattern's intended use.  CHASM
  837. recognizes five different ways to represent immediate data.
  838.  
  839. A memory location can be used as an operand.  We've seen one way
  840. to do this, by enclosing it's address in brackets.  (You can now
  841. see why the brackets are needed.  Without them, you couldn't
  842. distinguish between an address and immediate data.)  If you've
  843. asked the assembler to set aside a section of memory for data
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.                                                                        13
  865.  
  866. (more on this latter), and put a label on the request, you can
  867. specify that point in memory by using the label.  Finally, there
  868. are a number of indirect ways to address memory locations, which
  869. you can read about in The 8086 Book.
  870.  
  871. The last major type of operands are labels.  Branching
  872. instructions require an operand to tell them where to branch *to*.
  873. In assembly language, you specify locations which may be branched
  874. to by putting a label on them.  You can then use the label as an
  875. operand on branches.
  876.  
  877. Often times, the order in which the operands are listed can be
  878. important.  For example, when moving a pattern from one place to
  879. another, you need to specify where the pattern is to come from,
  880. and where it's going.  The convention in general use is that the
  881. first operand is the *destination* and the second is the
  882. *source*.  Thus, to move the pattern in the DX register into the
  883. AX register, you would write:
  884.  
  885.         MOV AX,DX
  886.  
  887. This may take some getting used to, since when reading from left
  888. to right it seems reasonable to assume that the transfer goes in
  889. this direction as well.  However, since this convention is pretty
  890. well entrenched in the assembly language community, CHASM goes
  891. along with it.
  892.  
  893. The last part of an assembly language line is a *comment*.  The
  894. comment is totally ignored by the assembler, but is *vital* for
  895. humans who are attempting to understand the program.  Assembly
  896. language programs tend to be very hard to follow, and so it's
  897. particularly important to put in lots of comments so that you'll
  898. remember just what it was you were trying to do with a given
  899. piece of code.  Professional assembly language programmers put a
  900. comment on *every* line of code, explaining what it does, plus
  901. devoting many entire lines for additional explanations.  For an
  902. example of a professional assembly language program, you should
  903. examine the BIOS source listing given in the IBM Technical
  904. Referance manual.  Over *half* the text consists of comments!
  905.  
  906. Since the assembler ignores the comments, they cost you nothing
  907. in terms of size or speed of execution in the resulting machine
  908. language program.  This is in sharp contrast to BASIC, where each
  909. remark slows your program down and eats up precious memory.
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.                                                                        14
  931.  
  932.  
  933. Generally, a character is set aside to indicate to the assembler
  934. the beginning of a comment, so that it knows to skip over.  CHASM
  935. follows a common convention of reserving the semi-colon (;) for
  936. marking comments.
  937.  
  938. THE STACK
  939.  
  940. I've been dropping the name *stack* from time to time.  The stack
  941. is just a portion of memory which has been temporarily set aside
  942. to be used in a special way.
  943.  
  944. To get a picture of how the stack works, think of the spring
  945. loaded contraptions you sometimes see holding trays in a
  946. cafeteria.  As each tray is washed, the busboy puts it on top of
  947. the stack in the contraption.  Because the thing is spring loaded,
  948. the whole stack sinks down from the weight of the new tray, and
  949. the top of the stack ends up always being the same height off the
  950. floor.  When a customer takes a tray off the stack, the next one
  951. rises up to take it's place.
  952.  
  953. In the computer, the stack is used to hold data patterns, which
  954. are generally being passed from one program or subroutine to
  955. another.  By putting things on the stack, the receiving routine
  956. doesn't need to know a particular address to look for the
  957. information it needs, it just pulls them off the top of the
  958. stack.
  959.  
  960. There is some jargon associated with use of the stack.  Patterns
  961. are *pushed* onto the stack, and *popped* off.  Accordingly, there
  962. are a set of PUSH and POP instructions in the 8088's repertoire.
  963.  
  964. Because you don't need to keep track of where the patterns are
  965. actually being kept, the stack is often used as a scratch pad
  966. area, patterns being pushed when the register they're in is
  967. needed for some other purpose, then popped out when the register
  968. is free.  It's very common for the first few instructions of a
  969. subroutine to be a series of pushes to save the patterns which
  970. are occupying the registers its about to use.   This is referred
  971. to as *saving the state* of the registers.  The last thing the
  972. subroutine will do is pop the patterns back into the registers
  973. they came from, thus *restoring the state* of the registers.
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996.                                                                        15
  997.  
  998. Following the analogy of the cafeteria contraption, when you pop
  999. the stack, the pattern you get is the last one which was pushed.
  1000. When you pop a pattern off, the next-to-last thing pushed
  1001. automatically moves to the top, just as the trays rise up when a
  1002. customer removes one.  Everything comes off the stack in the
  1003. reverse order of which they went on.  Sometimes you'll see the
  1004. phrase "last in, first out" or *LIFO stack*.
  1005.  
  1006. Of course, there are no special spring loaded memory locations
  1007. inside the computer.  The stack is implemented using a register
  1008. which keeps track of where the top of the stack is currently
  1009. located.  When you push something, the pointer is moved to the
  1010. next available memory location, and the pattern is put in that
  1011. spot.  When something is popped, it is copied from the location
  1012. pointed at, then the pointer is moved back.  You don't have to
  1013. worry about moving the pointer because it's all done
  1014. automatically with the push and pop instructions.
  1015.  
  1016. The register set aside to hold the pointer is SP, and that's why
  1017. you don't want to monkey with SP.  You'll recall that to form an
  1018. address, two words are needed, an offset and a segment.  The
  1019. segment word for the stack is kept in the SS register, so you
  1020. should leave SS alone as well.  When you run the type of machine
  1021. language program that CHASM produces, DOS will automatically set
  1022. the SP and SS registers to reserve a stack capable of holding 128
  1023. words.
  1024.  
  1025. SOFTWARE INTERRUPTS
  1026.  
  1027. I have been religiously avoiding talking about the various
  1028. individual instructions the 8088 can carry out, because if I
  1029. didn't, this little primer would soon grow into a rather long
  1030. book.  However, there's one very important instruction, which when
  1031. you read about it in The 8088 Book, won't seem particularly
  1032. useful.  This section will discuss the *software interrupt*
  1033. instruction, and why it's so important.
  1034.  
  1035. The 8088 reserves the first 1024 bytes of memory for a series of
  1036. 256 *interrupt vectors*.  Each of these two word long interrupt
  1037. vectors is used to store the segment:offset address of a location
  1038. in memory.  When you execute a software interrupt instruction,
  1039. the the 8088 pushes the location of the next instruction of your
  1040. program onto the stack, then branches to the memory location
  1041. pointed at by the vector specified in the interrupt.
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.                                                                        16
  1063.  
  1064.  
  1065. This probably seems like a rather awkward way to branch around in
  1066. memory, and chances are you'd never use this method to get from
  1067. one part of your program to another.  The way these instructions
  1068. become important is that IBM has pre-loaded a whole series of
  1069. useful little (and not so little) machine language routines into
  1070. your computer, and set the interrupt vectors to point to them.
  1071. All of these routines are set up so that after doing their thing,
  1072. they use the location pushed on the stack by the interrupt
  1073. instruction to branch back to your program.
  1074.  
  1075. Some of these routines are a part of DOS, and documentation for
  1076. them can be found in Appendix D of the DOS manual.  The rest of
  1077. them are stored in ROM (read only memory) and comprise the *BIOS*,
  1078. or basic input/output system of the computer.  Details of the BIOS
  1079. routines can be found in Appendix A of IBM's Technical Referance
  1080. Manual.  IBM charges around $40 for Technical Referance, but the
  1081. information in Appendix A alone is easily worth the money.
  1082.  
  1083. The routines do all kinds of useful things, such as run the disk
  1084. drive for you, print characters on the screen, or read data from
  1085. the keyboard.  In effect, the software interrupts add a whole
  1086. series of very powerful operations to the 8088 instruction set.
  1087.  
  1088. A final point is that if you don't like the way that DOS or the
  1089. BIOS does something, the vectored interrupt system makes it very
  1090. easy to substitute your own program to handle that function.  You
  1091. just load your program and reset the appropriate interrupt vector
  1092. to point at your program rather than the resident routine.  This
  1093. is how all those RAM disk and print spooler programs work.  The
  1094. programs change the vector for disk drive or printer support to
  1095. point to themselves, and carry out the operations in their own
  1096. special way.
  1097.  
  1098. To make things easy for you, one of the DOS interrupt routines
  1099. has the function of resetting interrupt vectors to point at new
  1100. code.  Still another DOS interrupt routine is used to graft new
  1101. code onto DOS, so that it doesn't accidentally get wiped out by
  1102. other programs.  The whole thing is really quite elegant and easy
  1103. to use, and IBM is to be complimented for setting things up this
  1104. way.
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.  
  1125.  
  1126.  
  1127.  
  1128.                                                                        17
  1129.  
  1130. PSEUDO-OPERATIONS
  1131.  
  1132. Up to this point, I've implied that each line of an assembly
  1133. language program gets translated into a machine language
  1134. instruction.  In fact, this is not the case.  Most assemblers
  1135. recognize a series of *pseudo-operations* which are handled as
  1136. embedded commands to the assembler itself, not as an instruction
  1137. in the machine language program being built.  Almost invariably
  1138. you'll see the phrase "pseudo-operation" abbreviated down to
  1139. *pseudo-op*. Sometimes you'll see *assembler directive*, which
  1140. means the same thing, but just doesn't seem to roll off the
  1141. tongue as well as pseudo-op.
  1142.  
  1143. One very common pseudo-op is the *equate*, usually given mnemonic
  1144. *EQU*.  What this allows you to do is assign a name to a
  1145. frequently used constant.  Thereafter, anywhere you use that
  1146. name, the assembler automatically substitutes the equated
  1147. constant.  This process makes your program easier to read, since
  1148. in place of the somewhat meaningless looking pattern, you see a
  1149. name which tells you what the pattern is for.  It also makes your
  1150. program easier to modify, since if you decide to change the
  1151. constant, you only need to do it once, rather than all over the
  1152. program.
  1153.  
  1154. The only other type of pseudo-op I'll talk about here are those
  1155. for setting aside memory locations for data.  These pseudo-ops
  1156. tend to be quite idiosyncratic with each assembler.  CHASM
  1157. implements two such pseudo-ops: DB (declare byte) and DS (declare
  1158. storage).  DB is used to set aside small data areas, which can be
  1159. initialized to any pattern, one byte at a time.  DS sets up
  1160. relatively large areas, but all the locations are filled with the
  1161. same initial pattern.
  1162.  
  1163. If you put a label on a pseudo-op which sets aside data areas,
  1164. most assemblers allow you to use the label as an operand, in place
  1165. of the actual address of the location.  The assembler
  1166. automatically substitutes the address for the name during the
  1167. translation process.
  1168.  
  1169. Some assemblers have a great number of pseudo-ops.  CHASM
  1170. implements a couple more, which aren't discussed here.
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.  
  1193.  
  1194.                                                                        18
  1195.  
  1196. TUTORIAL
  1197.  
  1198. To conclude this primer, this section will walk through the
  1199. process of writting, assembling, and running a very simple
  1200. program.
  1201.  
  1202. The program will perform the function filled by the BASIC command
  1203. CLS, that is, it will clear the video screen and move the cursor
  1204. to the upper left hand corner.  In fact, this is a useful little
  1205. program, since the DOS environment doesn't provide any method of
  1206. clearing the screen.
  1207.  
  1208. There is a BIOS routine called VIDEO_IO which provides an
  1209. interface to the screen.  Access to VIDEO_IO is through software
  1210. interrupt number 16, and documentation can be found on pages A-43
  1211. and A-44 of Technical Referance.  VIDEO_IO actually performs 15
  1212. different screen handling functions.  We specify which function
  1213. we want, along with information needed by the individual
  1214. function, in the 8088 registers.  Our entire program will be made
  1215. up of putting the proper patterns into the registers, then
  1216. activating VIDEO_IO with an interrupt.
  1217.  
  1218. To clear the screen, we'll use VIDEO_IO's scroll up function.
  1219. What this does is move a portion of the screen up, filling the
  1220. vacated space with blanks.  We have to tell VIDEO_IO what portion
  1221. of the screen to scroll, and how far to scroll it.  We can get
  1222. the proper patterns into the right registers using the MOV
  1223. instruction, MOVing the patterns in as immediate data.  Here's
  1224. the code to do this:
  1225.  
  1226.  
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.                                                                        19
  1261.  
  1262.     MOV AH,6     ;this specifys we want a scroll
  1263.                  ;the CH/CL register pair specifies the row and
  1264.                  ;column of the upper left hand corner of the region
  1265.                  ;to be scrolled
  1266.     MOV CH,0     ;row = 0
  1267.     MOV CL,0     ;column = 0
  1268.                  ;the DH/DL pair does the same for the lower
  1269.                  ;right corner.
  1270.     MOV DH,24    ;row = 24
  1271.     MOV DL,79    ;column = 79
  1272.                  ;BH specifies what color to fill with
  1273.     MOV BH,7     ;we'll use black
  1274.                  ;AL specifies how far to scroll.
  1275.     MOV AL,0     ;pattern 0 means to blank out the whole region.
  1276.     INT 16       ;call video_io
  1277.  
  1278. Notice that none of the lines starts at the left margin (column
  1279. 1).  If they did, CHASM would think that the instruction mnemonic
  1280. was meant to be a label, and would get very confused.
  1281.  
  1282. Since the bit patterns are meant to represent numbers, I've
  1283. chosen to write down the immediate data as decimal numbers.  CHASM
  1284. will automatically translate into the proper patterns.  Notice
  1285. that since each of the high/low register pairs can be accessed as
  1286. a single 16 bit register, I could have moved the patterns for both
  1287. halves in at the same time.  I did it this way for clarity.  Note
  1288. also the profusion of comments.
  1289.  
  1290. The second half of the program has to move the cursor to the upper
  1291. left.  Again, all that's necessary is to load the registers and
  1292. execute the interrupt:
  1293.  
  1294.     MOV AH,2     ;specifies that we want to position the cursor.
  1295.                  ;the DH/DL pair specifies the row and column of
  1296.                  ;where we want the cursor.
  1297.     MOV DH,0     ;row = 0
  1298.     MOV DL,0     ;column = 0
  1299.                  ;BH specifies which display page
  1300.     MOV BH,0     ;put the cursor on page 0
  1301.     INT 16       ;call video_io
  1302.  
  1303.  
  1304.  
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324.  
  1325.  
  1326.                                                                        20
  1327.  
  1328. There's one last detail.  We have to warn the 8088 that it's come
  1329. to the end of our program, or it'll just keep executing whatever
  1330. random patterns are in memory after our stuff.  Remember
  1331. "crashing the system"?  One of DOS's vectored interrupts handles
  1332. program termination, returning you to DOS.  The last instruction
  1333. is:
  1334.  
  1335.    INT 32       ;return to DOS
  1336.  
  1337. After writing the program, we must now create a text file which
  1338. contains the lines of our program.  This is done using a text
  1339. editor, such as EDLIN, which comes on your DOS disk.  At this
  1340. point, you can either copy the above lines into a file using an
  1341. editor, or use the file CLS.ASM, which was included on your CHASM
  1342. disk.  CLS.ASM contains the above lines already entered for you,
  1343. if you'd rather not bother making your own file at the moment.
  1344.  
  1345. It's now time to assemble the program.  From DOS, you start CHASM
  1346. up by typing it's name:
  1347.  
  1348.    A> CHASM
  1349.  
  1350. CHASM will respond by printing a hello screen, and ask you to
  1351. press a key when you're done reading it.  When you do so, CHASM
  1352. will ask you some questions:
  1353.  
  1354.     Source code file name? [.asm]
  1355.  
  1356. Type in the name of the file which has your assembly language
  1357. program text in it, then press return.
  1358.  
  1359.     Direct listing to Printer (P), Screen (S), or Disk (D)?
  1360.  
  1361. CHASM wants to know where to send the listing produced during the
  1362. assembly process.  If you have a printer, turn it on then press
  1363. P. If you don't have a printer, press S.
  1364.  
  1365. The last question is:
  1366.  
  1367.     Name for object file? [xxx.com]
  1368.  
  1369. CHASM is asking for the name you'd like to give to the machine
  1370. language program which is about to be produced.  Just press enter
  1371. here. (We'll accept CHASM's default name)
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.  
  1391.  
  1392.                                                                        21
  1393.  
  1394.  
  1395. At this point CHASM will start accessing the disk drive, reading
  1396. in your program a line at a time.  A status line will appear at
  1397. the bottom of your screen, telling you how far along the
  1398. translation has gotten.  For this program, the whole process
  1399. takes about 2 1/2 minutes.
  1400.  
  1401. If the listing went to your printer, CHASM automatically returns
  1402. you to DOS when it's finished.  If it went to the screen, CHASM
  1403. waits for you to press a key to indicate that you're done
  1404. reading.  Near the bottom of the listing will be the message:
  1405.  
  1406. XXX Diagnostics Offered
  1407. YYY Errors Detected
  1408.  
  1409. If both numbers are 0, everything went fine.  If not, look up on
  1410. the listing for error messages, which will point out the
  1411. offending lines.  At this point, don't worry too much about what
  1412. the error messages say, just fix the line in your input file to
  1413. look like the text developed above.  Once you manage to get an
  1414. assembly with no errors, you're ready to go on.
  1415.  
  1416. Your disk will now contain machine language program whose name is
  1417. that of your input file, with an extension of .COM.  Check this
  1418. by typing DIR to get a directory listing.  Not only will this
  1419. confirm that the file is really there, it fills up your screen,
  1420. to give us something to clear.
  1421.  
  1422. To run the machine language program, you just type it's name,
  1423. with or without the .COM extension.  (Note: even though you don't
  1424. need to *enter* the it, the file has to have the .COM extension
  1425. for DOS to recognize it as a machine language program.) If
  1426. everything was done right, the screen will clear, and then the
  1427. DOS prompt, A>, will appear.
  1428.  
  1429. That's the entire process, from start to finish.  At this point
  1430. you should have enough of a start to be able to digest CHASM's
  1431. documentation and The 8086 Book, then begin to write your own
  1432. programs.  Good Luck!
  1433.