home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / chasm2.zip / PRIMER.DOC < prev    next >
Text File  |  1986-03-07  |  47KB  |  1,783 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.                     An Assembly Language Primer
  13.  
  14.                      (c) 1983 by David Whitman
  15.  
  16.  
  17.  
  18.  
  19.  
  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.                   TABLE OF CONTENTS
  70.  
  71.  
  72.     Introduction.......................................2
  73.  
  74.     The Computer As A Bit Pattern Manipulator..........3
  75.  
  76.     Digression: A Notation System for Bit Patterns.....5
  77.  
  78.     Addressing Memory..................................7
  79.  
  80.     The Contents of Memory: Data and Programs..........8
  81.  
  82.     The Dawn of Assembly Language......................9
  83.  
  84.     The 8088..........................................11
  85.  
  86.     Assembly Language Syntax..........................14
  87.  
  88.     The Stack.........................................17
  89.  
  90.     Software Interrupts...............................19
  91.  
  92.     Pseudo-Operations.................................21
  93.  
  94.     Tutorial..........................................23
  95.  
  96.  
  97.  
  98.  
  99.  
  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.                                                                     2
  135.     >>INTRODUCTION<<
  136.  
  137.     Many people requesting CHASM have indicated that they are
  138.     interested in *learning* assembly language.  They are beginners,
  139.     and have little idea just where to start.  This primer is
  140.     directed to those users.  Experienced users will probably find
  141.     little here that they do not already know.
  142.  
  143.     Being a primer, this text will not teach you everything there is
  144.     to know about assembly language programming.  It's purpose is to
  145.     give you some of the vocabulary and general ideas which will help
  146.     you on your way.
  147.  
  148.     I must make a small caveat: I consider myself a relative beginner
  149.     in assembly language programming.  A big part of the reason for
  150.     writing CHASM was to try and learn this branch of programming
  151.     from the inside out.  I think I've learned quite a bit, but it's
  152.     quite possible that some of the ideas I relate here may have some
  153.     small, or even large, flaws in them.  Nonetheless, I have
  154.     produced a number of working assembly language programs by
  155.     following the ideas presented here.
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.                                                                     3
  201.     >>THE COMPUTER AS A BIT PATTERN MANIPULATOR.<<
  202.  
  203.     We all have some conception about what a computer does.  On one
  204.     level, it may be thought of as a machine which can execute BASIC
  205.     programs.  Another idea is that the computer is a number
  206.     crunching device.  As I write this primer, I'm using my computer
  207.     as a word processor.
  208.  
  209.     I'd like to introduce a more general concept of just what sort of
  210.     machine a computer is: a bit pattern manipulator.
  211.  
  212.     I'm certain that everyone has been introduced to the idea of a
  213.     *bit*.  (Note: Throughout this primer, a word enclosed in
  214.     *asterisks* is to be read as if it were in italics.)  A bit has
  215.     two states: on and off, typically represented with the symbols
  216.     "1"  and "0".  In this context, DON'T think of 1 and 0 as
  217.     numbers.  They are merely convenient shorthand labels for the
  218.     state of a bit.
  219.  
  220.     The memory of your computer consists of a huge collection of
  221.     bits, each of which could be in either the 1 or 0 (on or off)
  222.     state.
  223.  
  224.     At the heart of your computer is an 8088 microprocessor chip,
  225.     made by Intel.  What this chip can do is manipulate the bits
  226.     which make up the memory of the computer.
  227.  
  228.     The 8088 likes to handle bits in chunks, and so we'll introduce
  229.     special names for the two sizes of bit chunks the 8088 is most
  230.     happy with.  A *byte* will refer to a collection of eight bits.
  231.     A *word* consists of two bytes, or equivalently, sixteen bits.
  232.  
  233.     A collection of bits holds a pattern, determined by the state of
  234.     its individual bits.  Here are some typical byte long patterns:
  235.  
  236.     10101010         11111111         00001111
  237.  
  238.     If you've had a course in probability, it's quite easy to work
  239.     out that there are 256 possible patterns that a byte could hold.
  240.     similarly, a word can hold 65,536 different patterns.
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.                                                                     4
  267.     All right, now for the single most important idea in assembly
  268.     language programming.  Are you sitting down?  These bit patterns
  269.     can be used to represent other sets of things, by mapping each
  270.     pattern onto a member of the other set.  Doesn't sound like much,
  271.     but IBM has made *BILLIONS* off this idea.
  272.  
  273.     For example, by mapping the patterns a word can hold onto the set
  274.     of integers, you can represent either the numbers from 0 to 65535
  275.     or -32768 to 32767, depending on the exact mapping you use.  You
  276.     might recognize these as the BASIC's range of possible line
  277.     numbers, and possible values for integer variables.  This
  278.     explains these somewhat arbitrary seeming limits: BASIC uses
  279.     words of memory to hold line numbers and integer variables.
  280.  
  281.     As another example, you could map the patterns a byte can hold
  282.     onto a series of arbitrarily chosen little pictures which might
  283.     be displayed on a video screen.  If you look at the table in
  284.     the back of your BASIC manual, you'll notice that there are
  285.     *exactly* 256 different characters that can be displayed on your
  286.     screen.  Your computer uses a byte of memory to tell it what
  287.     character to display at each location of the video screen.
  288.  
  289.     Without getting too far ahead of myself, I'll just casually
  290.     mention that there are about 256 fundamental ways the 8088 can
  291.     manipulate the bit patterns stored in memory.  This suggests
  292.     another mapping which we'll discuss in more detail later.
  293.  
  294.     The point of this discussion is that we can use bit patterns to
  295.     represent anything we want, and by manipulating the patterns in
  296.     different ways, we can produce results which have significance in
  297.     terms of what we're choosing to represent.
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  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.                                                                     5
  333.     >>DIGRESSION: A NOTATION SYSTEM FOR BIT PATTERNS<<
  334.  
  335.     Because of their importance, it would be nice to have a
  336.     convenient way to represent the various bit patterns we'll be
  337.     talking about.  We already have one way, by listing the states of
  338.     the individual bits as a series of 1's and 0's.  However, this
  339.     system is somewhat clumsy, and error prone.  Are the following
  340.     word patterns identical or different?
  341.  
  342.     1111111011111111                         1111111101111111
  343.  
  344.     You probably had trouble telling them apart.  It's easier to tell
  345.     that they're different by breaking them down into more manageable
  346.     pieces, and comparing the pieces.  Here are the same two patterns
  347.     broken down into four bit chunks:
  348.  
  349.     1111 1110 1111 1111                      1111 1111 0111 1111
  350.  
  351.     Some clown has given the name *nybble* to a chunk of 4 bits,
  352.     presumably because 4 bits are half a byte.  A nybble is fairly
  353.     easy to handle.  There are only 16 possible nybble long patterns,
  354.     and most people can distinguish between the patterns quite
  355.     easily.
  356.  
  357.     Each nybble pattern has been given a unique symbol agreed upon by
  358.     computer scientists.  The first 10 patterns were given symbols
  359.     "0" through "9", and when they ran out of digit style symbols,
  360.     they used the letters "A" through "F" for the last six patterns.
  361.     Below is the "nybble pattern code":
  362.  
  363.     0000 = 0    0001 = 1    0010 = 2    0011 = 3
  364.  
  365.     0100 = 4    0101 = 5    0110 = 6    0111 = 7
  366.  
  367.     1000 = 8    1001 = 9    1010 = A    1011 = B
  368.  
  369.     1100 = C    1101 = D    1110 = E    1111 = F
  370.  
  371.     Using the nybble code, we can represent the two similar word
  372.     patterns given above, with the following more manageable
  373.     shorthand versions:
  374.  
  375.                    FEFF       FF7F
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.                                                                     6
  399.     Of course, the assignment of the symbols for the various nybble
  400.     patterns was not so arbitrary as I've tried to make it appear.  A
  401.     perceptive reader who has been exposed to binary numbers will
  402.     have noticed an underlying system to the assignments.  If the 1's
  403.     and 0's of the patterns are interpreted as actual *numbers*,
  404.     rather than mere symbols for bit states, the first 10 patterns
  405.     correspond to binary numbers whose decimal representation is the
  406.     symbol assigned to the pattern.
  407.  
  408.     The last six patterns receive the symbols "A" through "F", and
  409.     taken together, the symbols 0 through F constitute the digits of
  410.     the *hexadecimal* number system.  Thus, the symbols assigned to
  411.     the different nybble patterns were born out of historical
  412.     prejudice in thinking of the computer as strictly a number
  413.     handling machine.  Although this is an important interpretation
  414.     of these symbols, for the time being it's enough to merely think
  415.     of them as a shorthand way to write down bit patterns.
  416.  
  417.     Because some nybble patterns can look just like a number, it's
  418.     often necessary to somehow indicate that we're talking about a
  419.     pattern.  In BASIC, you do this by adding the characters &H to
  420.     the beginning of the pattern: &H1234.  A more common convention
  421.     is to just add the letter H to the end of the pattern: 1234H.  In
  422.     both conventions, the H is referring to hexadecimal.
  423.  
  424.     Eventually you'll want to learn about using the hexadecimal
  425.     number system, since it is an important way to use bit patterns.
  426.     I'm not going to discuss it in this primer, because a number of
  427.     books have much better treatments of this topic than I could
  428.     produce.  Consider this an advanced topic you'll want to fill in
  429.     later.
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.                                                                     7
  465.     >>ADDRESSING MEMORY<<
  466.  
  467.     As stated before, the 8088 chip inside your computer can
  468.     manipulate the bit patterns which make up the computer's memory.
  469.     Some of the possible manipulations are copying patterns from one
  470.     place to another, turning on or turning off certain bits, or
  471.     interpreting the patterns as numbers and performing arithmetic
  472.     operations on them.  To perform any of these actions, the 8088
  473.     has to know what part of memory is to be worked on.  A specific
  474.     location in memory is identified by its *address*.
  475.  
  476.     An address is a pointer into memory.  Each address points to the
  477.     beginning of a byte long chunk of memory.  The 8088 has the
  478.     capability to distinguish 1,048,576 different bytes of memory.
  479.  
  480.     By this point, it probably comes as no surprise to hear that
  481.     addresses are represented as patterns of bits.  It takes 20 bits
  482.     to get a total of 1,048,576 different patterns, and thus an
  483.     address may be written down as a series of 20 bits (or 5 nybble
  484.     codes).  For example, DOS stores a pattern which encodes
  485.     information about what equipment is installed on your IBM PC in
  486.     the word which begins at location 00410.  Interpreting the
  487.     address as a hex number, the second byte of this word has an
  488.     address 1 greater than 00410, or 00411.
  489.  
  490.     The 8088 isn't very happy handling 20 bits at a time.  The
  491.     biggest chunk that's convenient for it to use is a 16 bit word.
  492.     The 8088 actually calculates 20 bit addresses as the combination
  493.     of two words, a segment word and an offset word.  The combination
  494.     process involves interpreting the two patterns as hexadecimal
  495.     numbers and adding them.  The way that two 16 bit patterns can be
  496.     combined to give one 20 bit pattern is that the two patterns are
  497.     added out of alignment by one nybble:
  498.  
  499.         0040      4 nybble segment
  500.          0010     4 nybble offset
  501.        --------
  502.         00410     5 nybble address
  503.  
  504.     Because of this mechanism for calculating addresses, they will
  505.     often be written down in what's called segment:offset form.
  506.     Thus, the address in above calculation could be written:
  507.  
  508.     0040:0010
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.                                                                     8
  531.     >>MEMORY CONTENTS: DATA AND PROGRAMS<<
  532.  
  533.     The contents of memory may be broken down into two broad classes.
  534.     The first is *data*, just raw patterns of bits for the 8088 to
  535.     work on.  The significance of the patterns is determined by what
  536.     the computer is being used for at any given time.
  537.  
  538.     The second class of memory contents are *instructions*.  The 8088
  539.     can look at memory and interpret a pattern it sees there as
  540.     specifying one of the 200 some fundamental operations it knows
  541.     how to do.  This mapping of patterns onto operations is called
  542.     the *machine language* of the 8088.  A machine language *program*
  543.     consists of a series of patterns located in consecutive memory
  544.     locations, whose corresponding operations perform some useful
  545.     process.
  546.  
  547.     Note that there is no way for the 8088 to know whether a given
  548.     pattern is meant to be an instruction, or a piece of data to
  549.     operate on.  It is quite possible for the chip to accidentally
  550.     begin reading what was intended to be data, and interpret it as a
  551.     program.  Some pretty bizarre things can occur when this happens.
  552.     In assembly language programming circles, this is known as
  553.     "crashing the system".
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.                                                                     9
  597.     >>THE DAWN OF ASSEMBLY LANGUAGE<<
  598.  
  599.     Unless you happen to be an 8088 chip, the patterns which make up
  600.     a machine language program can be rather incomprehensible.  For
  601.     example, the pattern which tells the 8088 to flip all the bits in
  602.     the byte at address 5555 is:
  603.  
  604.     F6 16 55 55
  605.  
  606.     which is not very informative, although you can see the 5555
  607.     address in there.  In ancient history, the old wood-burning and
  608.     vacuum tube computers were programmed by laboriously figuring out
  609.     bit patterns which represented the series of instructions
  610.     desired.  Needless to say, this technique was incredibly tedious,
  611.     and very prone to making errors.  It finally occurred to these
  612.     ancestral programmers that they could give the task of figuring
  613.     out the proper patterns to the computer itself, and assembly
  614.     language programming was born.
  615.  
  616.     Assembly language represents each of the many operations that the
  617.     computer can do with a *mnemonic*, a short, easy to remember
  618.     series of letters.  For example, in boolean algebra, the logical
  619.     operation which inverts the state of a bit is called "not", and
  620.     hence the assembly language equivalent of the preceding machine
  621.     language pattern is:
  622.  
  623.         NOTB [5555]
  624.  
  625.     The brackets around the 5555 roughly mean "the memory location
  626.     addressed by".  The "B" at the end of "NOTB" indicates that we
  627.     want to operate on a byte of memory, not a word.
  628.  
  629.     Unfortunately, the 8088 can't make head nor tail of the string of
  630.     characters "NOTB".  What's needed is a special program to run on
  631.     the 8088 which converts the string "NOTB" into the pattern F6 16.
  632.     This program is called an assembler.  A good analogy is that an
  633.     assembler program is like a meat grinder which takes in assembly
  634.     language and gives out machine language.
  635.  
  636.     Typically, an assembler reads a file of assembly language and
  637.     translates it one line at a time, outputting a file of machine
  638.     language.  Often times the input file is called the *source file*
  639.     and the output file is called the *object file*.  The machine
  640.     language patterns produced are called the *object code*.
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.                                                                    10
  663.     Also produced during the assembly process is a *listing*, which
  664.     summarizes the results of the assembly process.  The listing
  665.     shows each line from the source file, along with the shorthand
  666.     "nybble code" representation of the object code produced.  In the
  667.     event that the assembler was unable to understand any of the
  668.     source lines, it inserts error messages in the listing, pointing
  669.     out the problem.
  670.  
  671.     The primeval assembly language programmers had to write their
  672.     assembler programs in machine language, because they had no other
  673.     choice.  Not being a masochist, I wrote CHASM in Turbo Pascal.
  674.     When you think about it, there's a sort of circular logic in
  675.     action here. Some programmers at Borland wrote the Turbo Pascal
  676.     in assembly language, and I used Turbo to write an assembler.
  677.     Someday, I hope to use the present version of CHASM to produce a
  678.     machine language version, which will run about a ten times
  679.     faster, and at the same time bring this crazy process full
  680.     circle.
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.                                                                    11
  729.     >>THE 8088<<
  730.  
  731.     The preceding discussions have (I hope) given you some very
  732.     general background, a world view if you will, about assembly and
  733.     machine language programming.  At this point, I'd like to get
  734.     into a little more detail, beginning by examining the internal
  735.     structure of the 8088 microprocessor from the programmer's point
  736.     of view.  This discussion is a condensation of information which
  737.     I obtained from "The 8086 Book" which was written by Russell
  738.     Rector and George Alexy, and published by Osborne/McGraw-Hill.
  739.     Once you've digested this, I'd recommend going to The 8086 Book
  740.     for a deeper treatment.
  741.  
  742.     Inside the 8088 are a number of *registers* each of which can
  743.     hold a 16 bit pattern.  In assembly language, each of the
  744.     registers has a two letter mnemonic name.  There are 14
  745.     registers, and their mnemonics are:
  746.  
  747.     AX BX CX DX     SP BP    SI DI     CS DS SS ES    PC ST
  748.  
  749.     Each of the registers are a little different and have different
  750.     intended uses, but they can be grouped into some broad classes.
  751.  
  752.     The *general purpose* registers (AX BX CX DX) are just that.
  753.     These are registers which hold patterns pulled in from memory
  754.     which are to be worked on within the 8088.  You can use these
  755.     registers for just about anything you want.
  756.  
  757.     Each of the general purpose registers can be broken down into two
  758.     8 bit registers, which have names of their own.  Thus, the CX
  759.     register is broken down into the CH and CL registers.  The "H"
  760.     and "L" stand for high and low respectively.  Each general
  761.     purpose register breaks down into a high/low pair.
  762.  
  763.     The AX register, and its 8 bit low half, the AL register, are
  764.     somewhat special.  Mainly for historical reasons, these registers
  765.     are referred to as the 16 bit and 8 bit *accumulators*.  Some
  766.     operations of the 8088 can only be carried out on the contents of
  767.     the accumulators, and many others are faster when used in
  768.     conjunction with these registers.
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.                                                                    12
  795.     Another group of registers are the *segment* registers (CS DS SS
  796.     ES).  These registers hold segment values for use in calculating
  797.     memory addresses.  The CS, or code segment register, is used
  798.     every  time the 8088 accesses memory to read an instruction
  799.     pattern.  The  DS, or data segment register, is used for bringing
  800.     data patterns in.  The SS register is used to access the stack
  801.     (more about the stack later).  The ES is the extra segment
  802.     register.  A very few special instructions use the ES register to
  803.     access memory, plus you can override use of the DS register and
  804.     substitute the ES register if you need to maintain two separate
  805.     data areas.
  806.  
  807.     The *pointer* (SP BP) and *index* (DI SI) registers are used to
  808.     provide indirect addressing, which is an very powerful technique
  809.     for accessing memory.  Indirect addressing is beyond the scope of
  810.     this little primer, but is discussed in The 8086 Book.  The SP
  811.     register is used to implement a stack in memory. (again, more
  812.     about the stack later)  Besides their special function, the BP,
  813.     DI and SI registers can be used as additional general purpose
  814.     registers.  Although it's possible to directly manipulate the
  815.     value in the SP register, it's best to leave it alone, since you
  816.     could wipe out the stack.
  817.  
  818.     Finally, there are two registers which are relatively
  819.     inaccessible to direct manipulation.  The first is the *program
  820.     counter*, PC.  This register always contains the offset part of
  821.     the address of the next instruction to be executed.  Although
  822.     you're not allowed to just move values into this register, you
  823.     *can* indirectly affect its contents, and hence the next
  824.     instruction to be executed, using operations which are equivalent
  825.     to BASIC's GOTO and GOSUB instructions.  Occasionally, you will
  826.     see the PC referred to as the *IP*, which stands for instruction
  827.     pointer.
  828.  
  829.     The last register is also relatively inaccessible.  This is the
  830.     *status* register, ST.  This one has a *two* alternate names, so
  831.     watch for FL (flag register) and PSW (program status word).  The
  832.     latter is somewhat steeped in history, since this was the name
  833.     given to a special location in memory which served a similar
  834.     function on the antique IBM 360 mainframe.
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.                                                                    13
  861.     The status register consists of a series of one bit *flags* which
  862.     can affect how the 8088 works.  There are special instructions
  863.     which allow you to set or clear some of the flags.  In addition,
  864.     many instructions affect the state of the flags, depending on
  865.     their outcome.  For example, one of the bits of the status
  866.     register is called the Zero flag.  Any operation which ends up
  867.     generating a bit pattern of all 0's automatically sets the Zero
  868.     flag on.
  869.  
  870.     Setting the flags doesn't seem to do much, until you know that
  871.     there a whole set of conditional branching instructions which
  872.     cause the equivalent to a BASIC GOTO if the particular flag
  873.     pattern they look for is set.  In assembly language, the only way
  874.     to make a decision and branch accordingly is via this flag
  875.     testing mechanism.
  876.  
  877.     Although some instructions implicitly affect the flags, there are
  878.     a series of instructions whose *only* effect is to set the flags,
  879.     based on some test or comparison.  It's very common to see one
  880.     of these comparison operations used to set the flags just before
  881.     a conditional branch.  Taken together, the two instructions are
  882.     exactly equivalent to BASIC's:
  883.  
  884.     IF (comparison) THEN GOTO (linenumber)
  885.  
  886.  
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900.  
  901.  
  902.  
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.                                                                    14
  927.     >>ASSEMBLY LANGUAGE SYNTAX<<
  928.  
  929.     In general, each line of an assembly language program translates
  930.     to a set of patterns which specify one fundamental operation for
  931.     the 8088 to carry out.
  932.  
  933.     Each line may consist of one or more of the following parts:
  934.  
  935.     First, a label, which is just a marker for the assembler to use.
  936.     If you want to branch to an instruction from some other part of
  937.     the program, you put a label on the instruction.  When you want
  938.     to branch, you refer to the label.  In general, the label can be
  939.     any string of characters you want.  A good practice is to use a
  940.     name which reminds you what that particular part of the program
  941.     does. CHASM will assume that any string of characters which
  942.     starts in the first column of a line is intended to be a label.
  943.  
  944.     After the label, or if the text of the line starts to the right
  945.     of the first column, at the beginning of the text, comes an
  946.     instruction mnemonic.  This specifies the operation that the line
  947.     is asking for.  For a list of the 200-odd mnemonics, along with
  948.     the instructions they stand for, see The 8086 Book.
  949.  
  950.     Most of the 8088 instructions require that you specify one or
  951.     more *operands*.  The operands are what the operation is to work
  952.     on, and are listed after the instruction mnemonic.
  953.  
  954.     There are a number of possible operands.  Probably the most
  955.     common are registers, specified by their two letter mnemonics.
  956.  
  957.     Another operand type is *immediate data*, a pattern of bits to be
  958.     put somewhere or compared or combined with some other pattern.
  959.     Generally immediate data is specified by its nybble code
  960.     representation, marked as such by following it with the letter
  961.     "H".  Most assemblers allow alternate ways to specify immediate
  962.     data which emphasize the pattern's intended use.  CHASM
  963.     recognizes ten different ways of representing immediate data.
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.                                                                    15
  993.     A memory location can be used as an operand.  We've seen one way
  994.     to do this, by enclosing its address in brackets.  (You can now
  995.     see why the brackets are needed.  Without them, the assembler
  996.     couldn't distinguish between an address and immediate data.)  If
  997.     you've asked the assembler to set aside a section of memory for
  998.     data (more on this latter), and put a label on the request, you
  999.     can specify that point in memory by using the label.  Finally,
  1000.     there are a number of indirect ways to address memory locations,
  1001.     which you can read about in The 8086 Book.
  1002.  
  1003.     The last major type of operands are labels.  Branching
  1004.     instructions require an operand to tell them where to branch
  1005.     *to*.  In assembly language, you specify locations which may be
  1006.     branched to by putting a label on them.  You can then use the
  1007.     label as an operand on branches.
  1008.  
  1009.     Often times, the order in which the operands are listed can be
  1010.     important.  For example, when moving a pattern from one place to
  1011.     another, you need to specify where the pattern is to come from,
  1012.     and where it's going.  The convention in general use is that the
  1013.     first operand is the *destination* and the second is the
  1014.     *source*.  Thus, to move the pattern in the DX register into the
  1015.     AX register, you would write:
  1016.  
  1017.             MOV AX,DX
  1018.  
  1019.     This may take some getting used to, since when reading from left
  1020.     to right it seems reasonable to assume that the transfer goes in
  1021.     this direction as well.  However, since this convention is pretty
  1022.     well entrenched in the assembly language community, CHASM goes
  1023.     along with it.
  1024.  
  1025.     The last part of an assembly language line is a *comment*.  The
  1026.     comment is totally ignored by the assembler, but is *vital* for
  1027.     humans who are attempting to understand the program.  Assembly
  1028.     language programs tend to be very hard to follow, and so it's
  1029.     particularly important to put in lots of comments so that you'll
  1030.     remember just what it was you were trying to do with a given
  1031.     piece of code.  Professional assembly language programmers put a
  1032.     comment on *every* line of code, explaining what it does, plus
  1033.     devoting many entire lines for additional explanations.  For an
  1034.     example, you should examine the BIOS source listing given in the
  1035.     IBM Technical Reference manual.  Over *half* the text consists of
  1036.     comments!
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.                                                                    16
  1059.     Since the assembler ignores the comments, they cost you nothing
  1060.     in terms of size or speed of execution in the resulting machine
  1061.     language program.  This is in sharp contrast to BASIC, where each
  1062.     remark slows your program down and eats up precious memory.
  1063.  
  1064.     Generally, a character is set aside to indicate to the assembler
  1065.     the beginning of a comment, so that it knows to skip over.  CHASM
  1066.     follows a common convention of reserving the semi-colon (;) for
  1067.     marking comments.
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.                                                                    17
  1125.     >>THE STACK<<
  1126.  
  1127.     I've been dropping the name *stack* from time to time.  The stack
  1128.     is just a portion of memory which has been temporarily set aside
  1129.     to be used in a special way.
  1130.  
  1131.     To get a picture of how the stack works, think of the spring
  1132.     loaded contraptions you sometimes see holding trays in a
  1133.     cafeteria.  As each tray is washed, the busboy puts it on top of
  1134.     the stack in the contraption.  Because the thing is spring
  1135.     loaded, the whole stack sinks down from the weight of the new
  1136.     tray, and the top of the stack ends up always being the same
  1137.     height off the floor.  When a customer takes a tray off the
  1138.     stack, the next one rises up to take its place.
  1139.  
  1140.     In the computer, the stack is used to hold data patterns, which
  1141.     are generally being passed from one program or subroutine to
  1142.     another.  By putting things on the stack, the receiving routine
  1143.     doesn't need to know a particular address to look for the
  1144.     information it needs, it just pulls them off the top of the
  1145.     stack.
  1146.  
  1147.     There is some jargon associated with use of the stack.  Patterns
  1148.     are *pushed* onto the stack, and *popped* off.  Accordingly,
  1149.     there are a set of PUSH and POP instructions in the 8088's
  1150.     repertoire.
  1151.  
  1152.     Because you don't need to keep track of where the patterns are
  1153.     actually being kept, the stack is often used as a scratch pad
  1154.     area, patterns being pushed when the register they're in is
  1155.     needed for some other purpose, then popped out when the register
  1156.     is free.  It's very common for the first few instructions of a
  1157.     subroutine to be a series of pushes to save the patterns which
  1158.     are occupying the registers it's about to use.   This is referred
  1159.     to as *saving the state* of the registers.  The last thing the
  1160.     subroutine will do is pop the patterns back into the registers
  1161.     they came from, thus *restoring the state* of the registers.
  1162.  
  1163.     Following the analogy of the cafeteria contraption, when you pop
  1164.     the stack, the pattern you get is the last one which was pushed.
  1165.     When you pop a pattern off, the next-to-last thing pushed
  1166.     automatically moves to the top, just as the trays rise up when a
  1167.     customer removes one.  Everything comes off the stack in the
  1168.     reverse order of which they went on.  Sometimes you'll see the
  1169.     phrase "last in, first out" or *LIFO stack*.
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.                                                                    18
  1191.     Of course, there are no special spring loaded memory locations
  1192.     inside the computer.  The stack is implemented using a register
  1193.     which keeps track of where the top of the stack is currently
  1194.     located.  When you push something, the pointer is moved to the
  1195.     next available memory location, and the pattern is put in that
  1196.     spot.  When something is popped, it is copied from the location
  1197.     pointed at, then the pointer is moved back.  You don't have to
  1198.     worry about moving the pointer because it's all done
  1199.     automatically with the push and pop instructions.
  1200.  
  1201.     The register set aside to hold the pointer is SP, and that's why
  1202.     SP shouldn't be monkeyed with.  You'll recall that to form an
  1203.     address, two words are needed, an offset and a segment.  The
  1204.     segment word for the stack is kept in the SS register, so you
  1205.     should leave SS alone as well.  When you run the type of machine
  1206.     language program that CHASM produces, DOS will automatically set
  1207.     the SP and SS registers to reserve a stack capable of holding 128
  1208.     words.
  1209.  
  1210.  
  1211.  
  1212.  
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  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.                                                                    19
  1257.     >>SOFTWARE INTERRUPTS<<
  1258.  
  1259.     I have been religiously avoiding talking about the various
  1260.     individual instructions the 8088 can carry out, because if I
  1261.     didn't, this little primer would soon grow into a rather long
  1262.     book.  However, there's one very important instruction, which
  1263.     when you read about it in The 8088 Book, won't seem particularly
  1264.     useful.  This section will discuss the *software interrupt*
  1265.     instruction, INT, and why it's so important.
  1266.  
  1267.     The 8088 reserves the first 1024 bytes of memory for a series of
  1268.     256 *interrupt vectors*.  Each of these two word long interrupt
  1269.     vectors is used to store the segment:offset address of a location
  1270.     in memory.  When you execute a software interrupt instruction,
  1271.     the the 8088 pushes the location of the next instruction of your
  1272.     program onto the stack, then branches to the memory location
  1273.     pointed at by the vector specified in the interrupt.
  1274.  
  1275.     This probably seems like a rather awkward way to branch around in
  1276.     memory, and chances are you'd never use this method to get from
  1277.     one part of your program to another.  The way these instructions
  1278.     become important is that IBM has pre-loaded a whole series of
  1279.     useful little (and not so little) machine language routines into
  1280.     your computer, and set the interrupt vectors to point to them.
  1281.     All of these routines are set up so that after doing their thing,
  1282.     they use the location pushed on the stack by the interrupt
  1283.     instruction to branch back to your program.
  1284.  
  1285.     Some of these routines are a part of DOS, and documentation for
  1286.     them can be found in the DOS Technical Reference manual.  The
  1287.     rest of them are stored in ROM (read only memory) and comprise
  1288.     the *BIOS*, or basic input/output system of the computer.
  1289.     Details of the BIOS routines can be found in the Hardware
  1290.     Technical Reference Manual.  DOS and BIOS interrupt data is also
  1291.     available in Peter Norton's book "Programmer's Guide to the IBM
  1292.     PC".
  1293.  
  1294.     The routines do all kinds of useful things, such as run the disk
  1295.     drive for you, print characters on the screen, or read data from
  1296.     the keyboard.  In effect, the software interrupts add a whole
  1297.     series of very powerful operations to the 8088 instruction set.
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304.  
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.                                                                    20
  1323.     A final point is that if you don't like the way that DOS or the
  1324.     BIOS does something, the vectored interrupt system makes it very
  1325.     easy to substitute your own program to handle that function.  You
  1326.     just load your program and reset the appropriate interrupt vector
  1327.     to point at your program rather than the resident routine.  This
  1328.     is how all those RAM disk and print spooler programs work.  The
  1329.     programs change the vector for disk drive or printer support to
  1330.     point to themselves, and carry out the operations in their own
  1331.     special way.
  1332.  
  1333.     To make things easy for you, one of the DOS interrupt routines
  1334.     has the function of resetting interrupt vectors to point at new
  1335.     code.  Still another DOS interrupt routine is used to graft new
  1336.     code onto DOS, so that it doesn't accidentally get wiped out by
  1337.     other programs.  The whole thing is really quite elegant and easy
  1338.     to use, and IBM is to be complimented for setting things up this
  1339.     way.
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.                                                                    21
  1389.     >>PSEUDO-OPERATIONS<<
  1390.  
  1391.     Up to this point, I've implied that each line of an assembly
  1392.     language program gets translated into a machine language
  1393.     instruction.  In fact, this is not the case.  Most assemblers
  1394.     recognize a series of *pseudo-operations* which are handled as
  1395.     embedded commands to the assembler itself, not as an instruction
  1396.     in the machine language program being built.  Almost invariably
  1397.     you'll see the phrase "pseudo-operation" abbreviated down to
  1398.     *pseudo-op*. Sometimes you'll see *assembler directive*, which
  1399.     means the same thing, but just doesn't seem to roll off the
  1400.     tongue as well.
  1401.  
  1402.     One very common pseudo-op is the *equate*, usually given mnemonic
  1403.     *EQU*.  What this allows you to do is assign a name to a
  1404.     frequently used constant.  Thereafter, anywhere you use that
  1405.     name, the assembler automatically substitutes the constant.  This
  1406.     process makes your program easier to read, since in place of the
  1407.     somewhat meaningless looking pattern, you see a name which tells
  1408.     you what the pattern is for.  It also makes your program easier
  1409.     to modify, since if you decide to change the constant, you only
  1410.     need to do it once, rather than all over the program.
  1411.  
  1412.     The only other type of pseudo-op I'll talk about here are those
  1413.     for setting aside memory locations for data.  These pseudo-ops
  1414.     tend to be quite idiosyncratic with each assembler.  CHASM
  1415.     implements three such pseudo-ops: DB (declare bytes), DW (declare
  1416.     words) and DS (declare storage).  DB is used to set aside small
  1417.     data areas, which can be initialized to any pattern, one byte at
  1418.     a time.  DW is an analogous pseudo-op for setting asides whole
  1419.     words of memory, one at a time.  DS sets up relatively large
  1420.     areas, but all the locations are filled with the same initial
  1421.     pattern.
  1422.  
  1423.     If you put a label on a pseudo-op which sets aside data areas,
  1424.     most assemblers allow you to use the label as an operand, in
  1425.     place of the actual address of the location.  The assembler
  1426.     automatically substitutes the address for the name during the
  1427.     translation process.
  1428.  
  1429.     Some assemblers have a great number of pseudo-ops.  CHASM
  1430.     implements a few more, which aren't discussed here.
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.  
  1454.                                                                    22
  1455.     >>TUTORIAL<<
  1456.  
  1457.     To conclude this primer, this section will walk through the
  1458.     process of writing, assembling, and running a very simple
  1459.     program.
  1460.  
  1461.     Our program will just print a message on the video screen, and
  1462.     then return to DOS.  Although very simple, this program will
  1463.     demonstrate a number of points, including a DOS function call,
  1464.     setting aside memory for storage, and good programming form.
  1465.  
  1466.     The DOS technical reference manual (or Norton's book) discusses
  1467.     the various DOS functions and interrupts available to the
  1468.     assembly language programmer.   To print a text string to the
  1469.     video screen, we'll use function 9.  You should read the
  1470.     documentation for this function at this time.
  1471.  
  1472.  
  1473.     Did it make any sense?  To use this function, we have to load the
  1474.     DX register with the address of a string in memory, specify
  1475.     function 9 by loading a "9" into the AH register, then ask DOS to
  1476.     do the printing by executing interrupt 21H.  Basically, we just
  1477.     set things up, and DOS does all the real work.
  1478.  
  1479.     Here's the code to do this:
  1480.  
  1481.          MOV AH, 9                 ;specify DOS function 9
  1482.          MOV DX, OFFSET(MESSAGE)   ;get address of string
  1483.          INT 21H                   ;call DOS
  1484.  
  1485.     Note that none of the lines starts at the left margin  (column
  1486.     one). If they did, CHASM would think that the instruction
  1487.     mnemonic was meant to be a label, and would get very confused.
  1488.     Also note that each line has a comment explaining what's going
  1489.     on.
  1490.  
  1491.     The second line needs a little explaining.  CHASM's OFFSET
  1492.     function returns the address of whatever is included in the
  1493.     parentheses, in this case, MESSAGE.  The assumption made here is
  1494.     that later in the program we will set aside a memory location
  1495.     containing our string to be printed, and give it the name
  1496.     "MESSAGE".
  1497.  
  1498.  
  1499.  
  1500.  
  1501.  
  1502.  
  1503.  
  1504.  
  1505.  
  1506.  
  1507.  
  1508.  
  1509.  
  1510.  
  1511.  
  1512.  
  1513.  
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520.                                                                    23
  1521.     Once we've printed our string, we want to return to DOS.  If we
  1522.     don't explicitly transfer control back to DOS, the 8088 will
  1523.     happily continue to execute whatever random patterns are in
  1524.     memory after our stuff.  Remember "crashing the system"?  One of
  1525.     DOS's reserved interrupts handles program termination, returning
  1526.     you to DOS.  The proper instruction is:
  1527.  
  1528.            INT 20H        ;return to DOS
  1529.  
  1530.     All that's left at this point is to set aside a chunk of memory
  1531.     containing a string to be printed.  We'll use CHASM's DB (Declare
  1532.     Bytes) pseudo-op to do this:
  1533.  
  1534.     MESSAGE DB  'Hello, World!$'     ;message to be printed
  1535.  
  1536.     The memory location is given the name "MESSAGE" because the line
  1537.     started with a "MESSAGE" as a label.  Now CHASM will know that
  1538.     the preceding OFFSET was talking about this memory location.  You
  1539.     don't need to worry about what the actual address of MESSAGE is,
  1540.     CHASM takes care of that.
  1541.  
  1542.     Fourteen bytes of memory get set aside here, containing the ASCII
  1543.     codes for the characters in "Hello, World!$".  Note that the
  1544.     string ends in the character "$".  DOS function 9 prints
  1545.     characters until it encounters a "$", at which point it stops.
  1546.     If you forget to put the "$" at the end of your string, you'll
  1547.     have the less-than-amusing experience of watching DOS attempt to
  1548.     print out the entire contents of memory.
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.  
  1572.  
  1573.  
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579.  
  1580.  
  1581.  
  1582.  
  1583.  
  1584.  
  1585.  
  1586.                                                                    24
  1587.     Bringing everything together, and adding a few comments at the
  1588.     beginning, here's our complete program:
  1589.  
  1590.     ;=====================================;
  1591.     ; HELLO    Version 1.00               ;
  1592.     ;          1984 by David Whitman      ;
  1593.     ;                                     ;
  1594.     ; Sample source file for CHASM.       ;
  1595.     ; Prints a greeting on the console.   ;
  1596.     ;=====================================;
  1597.  
  1598.             MOV AH, 9                 ;specify DOS function 9
  1599.             MOV DX, OFFSET(MESSAGE)   ;get address of string
  1600.             INT 21H                   ;call DOS
  1601.  
  1602.             INT 20H                   ;return to DOS
  1603.  
  1604.     MESSAGE DB  'Hello, World!$'      ;message to be printed
  1605.  
  1606.     After writing all this, we need to create a text file which
  1607.     contains the lines of our program.  You do this with a text
  1608.     editor or word processor.  (Of course, in real life you write the
  1609.     program using the editor in the first place.)
  1610.  
  1611.     CHASM likes its source files in "standard DOS" format, what some
  1612.     word processors call "document" or "ASCII mode".  Most word
  1613.     processors, and all straight text editors work in this format
  1614.     automatically.  Wordstar and Easywriter (and probably a few other
  1615.     packages) have their own special formats, but their manual should
  1616.     tell you how to make standard DOS files.
  1617.  
  1618.     At this point, make a standard DOS file named HELLO.ASM which
  1619.     contains the above program lines.  If you're feeling lazy, or if
  1620.     you run into problems, the file EXAMPLE.ASM on your CHASM disk
  1621.     has these lines already entered for you.  Just copy EXAMPLE.ASM
  1622.     into a new file called HELLO.ASM and you're in business.
  1623.  
  1624.     It's now time to assemble the program.  If it's not already
  1625.     there, copy HELLO.ASM onto your CHASM disk. Put the CHASM disk
  1626.     into your default drive, and start up CHASM by typing its name:
  1627.  
  1628.        A> CHASM
  1629.  
  1630.     CHASM will respond by printing a hello screen, and ask you to
  1631.     press a key when you're done reading it.  When you do so, CHASM
  1632.     will ask you some questions:
  1633.  
  1634.  
  1635.  
  1636.  
  1637.  
  1638.  
  1639.  
  1640.  
  1641.  
  1642.  
  1643.  
  1644.  
  1645.  
  1646.  
  1647.  
  1648.  
  1649.  
  1650.  
  1651.  
  1652.                                                                    25
  1653.  
  1654.         Source code file name? [.asm]
  1655.  
  1656.     Type in the HELLO.ASM, or just HELLO, then hit return.  (If you
  1657.     don't enter the file extension, CHASM assumes that it's .ASM)
  1658.  
  1659.         Direct listing to Printer (P), Screen (S), or Disk (D)?
  1660.  
  1661.     CHASM wants to know where to send the listing produced during the
  1662.     assembly process.  If you have a printer, turn it on, and then
  1663.     press P.  If you don't have a printer, press S.
  1664.  
  1665.     The last question is:
  1666.  
  1667.         Name for object file? [hello.com]
  1668.  
  1669.     CHASM is asking for the name you'd like to give to the machine
  1670.     language program which is about to be produced.  Just press enter
  1671.     here.  CHASM will name the program HELLO.COM
  1672.  
  1673.     At this point CHASM will start accessing the disk drive, reading
  1674.     in your program a line at a time.  A status line will appear at
  1675.     the bottom of your screen, telling you how far along the
  1676.     translation has gotten.  CHASM will make two passes over your
  1677.     file, outputing the translated program on the second pass.
  1678.  
  1679.     If the listing went to your printer, CHASM automatically returns
  1680.     you to DOS when finished.  If the listing went to the screen,
  1681.     CHASM waits for you to press a key to indicate that you're done
  1682.     reading.  Near the bottom of the listing will be the message:
  1683.  
  1684.     XXX Diagnostics Offered
  1685.     YYY Errors Detected
  1686.  
  1687.     If both numbers are 0, everything went fine.  If not, look up on
  1688.     the listing for error messages, which will point out the
  1689.     offending lines.  At this point, don't worry too much about what
  1690.     the error messages say, just fix the line in your input file to
  1691.     look like the text developed above.  Once you manage to get an
  1692.     assembly with no errors, you're ready to go on.
  1693.  
  1694.     Your disk will now contain a machine language program named
  1695.     HELLO.COM.  Confirm this by typing DIR to get a directory
  1696.     listing.  You should see the new program file listed.
  1697.  
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703.  
  1704.  
  1705.  
  1706.  
  1707.  
  1708.  
  1709.  
  1710.  
  1711.  
  1712.  
  1713.  
  1714.  
  1715.  
  1716.  
  1717.  
  1718.                                                                    26
  1719.     To run the machine language program, you just type its name,
  1720.     without the .COM extension.  (Note: even though you don't *enter*
  1721.     the "COM", the file has to have this extension for DOS to
  1722.     recognize it as a machine language program.)  Try it out now.
  1723.     From the DOS prompt, type: HELLO.  Your disk drive will whir for
  1724.     a second, then the message "Hello World!" will appear.
  1725.  
  1726.     For a further exercise, you might try printing a carriage return
  1727.     and then a line feed before the message, to space it down the
  1728.     screen a little.  Carriage return has ASCII code 13, and line
  1729.     feed is 10.  Read the CHASM User's Manual about the DB pseudo-op,
  1730.     and add these two characters at the beginning of STRING using
  1731.     their decimal representations.
  1732.  
  1733.     Try writing a new program called BEEP which writes the "bell"
  1734.     character to the screen.  You can use BEEP to signal the end of
  1735.     long batch files, or to annoy your co-workers.  Resist the urge
  1736.     to program a loop into BEEP.
  1737.  
  1738.     An even more advanced exercise would be to clear the screen
  1739.     before printing a message.  The easiest way to do this is to
  1740.     use a BIOS function, VIDEO_IO, documented on in the Hardware
  1741.     Technical Reference Manual.  The comments in the BIOS listing
  1742.     tell you what values to load into which registers to get VIDEO_IO
  1743.     to monkey with the screen for you.  Load the registers and
  1744.     execute INT 10H, once to blank the screen, and again to move the
  1745.     cursor to the upper left hand corner.
  1746.  
  1747.     If you've read all of this primer and run the above program,
  1748.     maybe modifying it a little, you're no longer a rank beginner.
  1749.     At this point you should have enough of a start to be able to
  1750.     digest the CHASM User's Manual and The 8086 Book, then begin to
  1751.     write your own programs.  Good Luck!
  1752.  
  1753.  
  1754.  
  1755.  
  1756.  
  1757.  
  1758.  
  1759.  
  1760.  
  1761.  
  1762.  
  1763.  
  1764.  
  1765.  
  1766.  
  1767.  
  1768.  
  1769.  
  1770.  
  1771.  
  1772.  
  1773.  
  1774.  
  1775.  
  1776.  
  1777.  
  1778.  
  1779.  
  1780.  
  1781.  
  1782.  
  1783.