home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / prog4 / assm.lzh / ASMTUTR2.DOC < prev    next >
Text File  |  1983-12-11  |  25KB  |  407 lines

  1.  
  2.         so.  An exception is the saving and restoring of registers at
  3.         entrance to and exit from a subroutine; here, if the subroutine is
  4.         long, you should probably PUSH everything which the caller may need
  5.         saved, whether you will use the register or not, and POP it in
  6.         reverse order at the end.
  7.         Be aware that CALL and INT push return address information on the
  8.         stack and RET and IRET pop it off.  It is a good idea to become
  9.         familiar with the structure of the stack.
  10.     c.  In practice, to invoke system services you will use the INT
  11.         instruction.  It is quite possible to use this instruction effec-
  12.         tively in a cookbook fashion without knowing precisely how it
  13.         works.
  14.     d.  The transfer of control instructions (CALL, RET, JMP) deserve care-
  15.         ful study to avoid confusion.  You will learn that these can be
  16.         classified as follows:
  17.         1)  all three have the capability of being either NEAR (CS register
  18.             unchanged) or FAR (CS register changed)
  19.         2)  JMPs and CALLs can be DIRECT (target is assembled into instruc-
  20.             tion) or INDIRECT (target fetched from memory or register)
  21.         3)  if NEAR and DIRECT, a JMP can be SHORT (less than 128 bytes
  22.             away) or LONG
  23.         In general, the third issue is not worth worrying about.  On a for-
  24.         ward jump which is clearly VERY short, you can tell the assembler
  25.         it is short and save one byte of code:
  26.                    JMP SHORT  CLOSEBY
  27.         On a backward jump, the assembler can figure it out for you.  On a
  28.         forward jump of dubious length, let the assembler default to a LONG
  29.         form; at worst you waste one byte.
  30.         Also leave the assembler to worry about how the target address is
  31.         to be represented, in absolute form or relative form.
  32.     e.  The conditional jump set is rather confusing when studied apart
  33.         from the assembler, but you do need to get a feeling for it.  The
  34.         interactions of the sign, carry, and overflow flags can get your
  35.         mind stuttering pretty fast if you worry about it too much.  What
  36.         is boils down to, though, is
  37.                 JZ        means what it says
  38.                 JNZ       means what it says
  39.                 JG reater this means "if the SIGNED difference is positive"
  40.                 JA bove   this means "if the UNSIGNED difference is positive"
  41.                 JL ess    this means "if the SIGNED difference is negative"
  42.                 JB elow   this means "if the UNSIGNED difference is negative"
  43.                 JC arry   assembles the same as JB; it's an aesthetic choice
  44.  
  45. IBM PC Assembly Language Tutorial                                        10
  46.  
  47.  
  48.         You should understand that all conditional jumps are inherently
  49.         DIRECT, NEAR, and "short"; the "short" part means that they can't
  50.         go more than 128 bytes in either direction.  Again, this is some-
  51.         thing you could easily imagine to be more of a problem than it is.
  52.         I follow this simple approach:
  53.         1)  When taking an abnormal exit from a block of code, I always use
  54.             an unconditional jump.  Who knows how far you are going to end
  55.             up jumping by the time the program is finished.  For example, I
  56.             wouldn't code this:
  57.                    TEST     AL,IDIBIT       ;Is the idiot bit on?
  58.                    JNZ      OYVEY           ;Yes.  Go to general cleanup
  59.             Rather, I would probably code this:
  60.                    TEST     AL,IDIBIT       ;Is the idiot bit on?
  61.                    JZ       NOIDIOCY        ;No.  I am saved.
  62.                    JMP      OYVEY           ;Yes.  What can we say...
  63.               NOIDIOCY:
  64.             The latter, of course, is a jump around a jump.  Some would say
  65.             it is evil, but I submit it is hard to avoid in this language.
  66.         2)  Otherwise, within a block of code, I use conditional jumps
  67.             freely.  If the block eventually grows so long that the assem-
  68.             bler starts complaining that my conditional jumps are too long
  69.             I
  70.             a)  consider reorganizing the block but
  71.             b)  also consider changing some conditional jumps to their
  72.                 opposite and use the "jump around a jump" approach as shown
  73.                 above.
  74.     Enough about specific instructions!
  75. 6.  Finally, in order to use the assembler effectively, you need to know
  76.     the default rules for which segment registers are used to complete
  77.     addresses in which situations.
  78.     a.  CS is used to complete an address which is the target of a NEAR
  79.         DIRECT jump.  On an NEAR INDIRECT jump, DS is used to fetch the
  80.         address from memory but then CS is used to complete the address
  81.         thus fetched.  On FAR jumps, of course, CS is itself altered.  The
  82.         instruction counter is always implicitly pointing in the code seg-
  83.         ment.
  84.     b.  SS is used to complete an address if BP is used in its formation.
  85.         Otherwise, DS is always used to complete a data address.
  86.     c.  On the string instructions, the target is always formed from ES and
  87.         DI.  The source is normally formed from DS and SI.  If there is a
  88.         segment prefix, it overrides the source not the target.
  89.  
  90. IBM PC Assembly Language Tutorial                                        11
  91.  
  92.  
  93. Learning about DOS
  94. __________________
  95. Learning about DOS
  96. Learning about DOS
  97. Learning about DOS
  98. I think the best way to learn about DOS internals is to read the technical
  99. appendices in the manual.  These are not as complete as we might wish, but
  100. they really aren't bad; I certainly have learned a lot from them.  What you
  101. don't learn from them you might eventually learn via judicious disassembly
  102. of parts of DOS, but that shouldn't really be necessary.
  103. From reading the technical appendices, you learn that interrupts 20H
  104. through 27H are used to communicate with DOS.  Mostly, you will use inter-
  105. rupt 21H, the DOS function manager.
  106. The function manager implements a great many services.  You request the
  107. individual services by means of a function code in the AH register.  For
  108. example, by putting a nine in the AH register and issuing interrupt 21H you
  109. tell DOS to print a message on the console screen.
  110. Usually, but by no means always, the DX register is used to pass data for
  111. the service being requested.  For example, on the print message service
  112. just mentioned, you would put the 16 bit address of the message in the DX
  113. register.  The DS register is also implicitly part of this argument, in
  114. keeping with the universal segmentation rules.
  115. In understanding DOS functions, it is useful to understand some history and
  116. also some of the philosophy of MS-DOS with regard to portability.  General-
  117. ly, you will find, once you read the technical information on DOS and also
  118. the IBM technical reference, you will know more than one way to do almost
  119. anything.  Which is best?  For example, to do asynch adapter I/O, you can
  120. use the DOS calls (pretty incomplete), you can use BIOS, or you can go
  121. directly to the hardware.  The same thing is true for most of the other
  122. primitive I/O (keyboard or screen) although DOS is more likely to give you
  123. added value in these areas.  When it comes to file I/O, DOS itself offers
  124. more than one interface.  For example, there are four calls which read data
  125. from a file.
  126. The way to decide rationally among these alternatives is by understanding
  127. the tradeoffs of functionality versus portability.  Three kinds of porta-
  128. bility need to be considered:  machine portability, operating system porta-
  129. bility (for example, the ability to assemble and run code under CP/M 86)
  130. and DOS version portability (the ability for a program to run under older
  131. versions of DOS>.
  132. Most of the functions originally offered in DOS 1.0 were direct descendents
  133. of CP/M functions; there is even a compatibility interface so that programs
  134. which have been translated instruction for instruction from 8080 assembler
  135. to 8086 assembler might have a reasonable chance of running if they use
  136. only the core CP/M function set.  Among the most generally useful in this
  137. original compatibility set are
  138.  
  139.  
  140.  
  141. IBM PC Assembly Language Tutorial                                        12
  142.  
  143.  
  144.   09   --  print a full message on the screen
  145.   0A   --  get a console input line with full DOS editing
  146.   0F   --  open a file
  147.   10   --  close a file (really needed only when writing)
  148.   11   --  find first file matching a pattern
  149.   12   --  find next file matching a pattern
  150.   13   --  erase a file
  151.   16   --  create a file
  152.   17   --  rename a file
  153.   1A   --  set disk transfer address
  154. The next set provide no function above what you can get with BIOS calls or
  155. more specialized DOS calls.  However, they are preferabƒâƒ9$ ƒα߃    ƒƒƒüα߃ƒÅŃƒƒÇǃƒ    ƒα߃ƒÅƒÇǃƒ    ƒ    ƒ        α߃ƒÅ냃ƒÇǃƒ    ƒ    ƒ        α߃ƒÅꃃƒÇǃƒ    ƒ8  ƒ    ƒ        α߃ƒÅ⃃ƒÇǃƒ    ƒ8  ƒ    ƒ        α߃ƒÅǃƒƒÇǃƒ    ƒƒ        α߃ƒÅüƒƒƒÇǃƒ    ƒnstruction set
  156. Phase 1:  Learn the architecture and instruction set
  157. The Morse book might seem like a lot of book to buy for just two really
  158. important chapters; other books devote a lot more space to the instruction
  159. set and give you a big beautiful reference page on each instruction.  And,
  160. some of the other things in the Morse book, although interesting, really
  161. aren't very vital and are covered too sketchily to be of any real help.
  162. The reason I like the Morse book is that you can just read it; it has a
  163. very conversational style, it is very lucid, it tells you what you really
  164. need to know, and a little bit more which is by way of background; because
  165. nothing really gets belabored to much, you can gracefully forget the things
  166. you don't use.  And, I very much recommend READING Morse rather than study-
  167. ing it.  Get the big picture at this point.
  168. Now, you want to concentrate on those things which are worth fixing in mem-
  169. ory.  After you read Morse, you should relate what you have learned to this
  170. outline.
  171. 1.  You want to fix in your mind the idea of the four segment registers
  172.     CODE, DATA, STACK, and EXTRA.  This part is pretty easy to grasp.  The
  173.     8086 and the 8088 use 20 bit addresses for memory, meaning that they
  174.     can address up to 1 megabyte of memory.  But, the registers and the
  175.     address fields in all the instructions are no more that 16 bits long.
  176.     So, how to address all of that memory?  Their solution is to put
  177.     together two 16 bit quantities like this:
  178.       calculation  SSSS0   ---- value in the relevant segment register SHL 4
  179.       depicted in   AAAA   ---- apparent address from register or instruction
  180.       hexadecimal --------
  181.                    RRRRR   ---- real address placed on address bus
  182.     In other words, any time memory is accessed, your program will supply a
  183.     sixteen bit address.  Another sixteen bit address is acquired from a
  184.     segment register, left shifted four bits (one nibble) and added to it
  185.     to form the real address.  You can control the values in the segment
  186.     registers and thus access any part of memory you want.  But the segment
  187.     registers are specialized:  one for code, one for most data accesses,
  188.     one for the stack (which we'll mention again) and one "extra" one for
  189.     additional data accesses.
  190.     Most people, when they first learn about this addressing scheme become
  191.     obsessed with converting everything to real 20 bit addresses.  After a
  192.     while, though, you get use to thinking in segment/offset form.  You
  193. IBM PC Assembly Language Tutorial                                         4
  194.  
  195.  
  196.     tend to get your segment registers set up at the beginning of the pro-
  197.     gram, change them as little as possible, and think just in terms of
  198.     symbolic locations in your program, as with any assembly language.
  199.       EXAMPLE:
  200.            MOV  AX,DATASEG
  201.            MOV  DS,AX          ;Set value of Data segment
  202.            ASSUME DS:DATASEG   ;Tell assembler DS is usable
  203.            .......
  204.            MOV  AX,PLACE       ;Access storage symbolically by 16 bit address
  205.     In the above example, the assembler knows that no special issues are
  206.     involved because the machine generally uses the DS register to complete
  207.     a normal data reference.
  208.     If you had used ES instead of DS in the above example, the assembler
  209.     would have known what to do, also.  In front of the MOV instruction
  210.     which accessed the location PLACE, it would have placed the ES segment
  211.     prefix.  This would tell the machine that ES should be used, instead of
  212.     DS, to complete the address.
  213.     Some conventions make it especially easy to forget about segment regis-
  214.     ters.  For example, any program of the COM type gets control with all
  215.     four segment registers containing the same value.  This program exe-
  216.     cutes in a simplified 64K address space.  You can go outside this
  217.     address space if you want but you don't have to.
  218. 2.  You will want to learn what other registers are available and learn
  219.     their personalities:
  220.        AX and DX are general purpose registers.  They become special only
  221.         when accessing machine and system interfaces.
  222.        CX is a general purpose register which is slightly specialized for
  223.         counting.
  224.        BX is a general purpose register which is slightly specialized for
  225.         forming base-displacement addresses.
  226.        AX-DX can be divided in half, forming AH, AL, BH, BL, CH, CL, DH,
  227.         DL.
  228.        SI and DI are strictly 16 bit.  They can be used to form indexed
  229.         addresses (like BX) and they are also used to point to strings.
  230.        SP is hardly ever manipulated.  It is there to provide a stack.
  231.        BP is a manipulable cousin to SP.  Use it to access data which has
  232.         been pushed onto the stack.
  233.        Most sixteen bit operations are legal (even if unusual) when per-
  234.         formed in SI, DI, SP, or BP.
  235.  
  236.  
  237. IBM PC Assembly Language Tutorial                                         5
  238.  
  239.  
  240. 3.  You will want to learn the classifications of operations available
  241.     WITHOUT getting hung up in the details of how 8086 opcodes are con-
  242.     structed.
  243.     8086 opcodes are complex.  Fortunately, the assembler opcodes used to
  244.     assemble them are simple.  When you read a book like Morse, you will
  245.     learn some things which are worth knowing but NOT worth dwelling on.
  246.     a.  8086 and 8088 instructions can be broken up into subfields and bits
  247.         with names like R/M, MOD, S and W. These parts of the instruction
  248.         modify the basic operation in such ways as whether it is 8 bit or
  249.         16 bit, if 16 bit, whether all 16 bits of the data are given,
  250.         whether the instruction is register to register, register to
  251.         memory, or memory to register, for operands which are registers,
  252.         which register, for operands which are memory, what base and index
  253.         registers should be used in finding the data.
  254.     b.  Also, some instructions are actually represented by several differ-
  255.         ent machine opcodes depending on whether they deal with immediate
  256.         data or not, or on other issues, and there are some expedited forms
  257.         which assume that one of the arguments is the most commonly used
  258.         operand, like AX in the case of arithmetic.
  259.     There is no point in memorizing any of this detail; just distill the
  260.     bottom line, which is, what kinds of operand combinations EXIST in the
  261.     instruction set and what kinds don't.  If you ask the assembler to ADD
  262.     two things and the two things are things for which there is a legal ADD
  263.     instruction somewhere in the instruction set, the assembler will find
  264.     the right instruction and fill in all the modifier fields for you.
  265.     I guess if you memorized all the opcode construction rules you might
  266.     have a crack at being able to disassemble hex dumps by eye, like you
  267.     may have learned to do somewhat with 370 assembler.  I submit to you
  268.     that this feat, if ever mastered by anyone, would be in the same class
  269.     as playing the "Minute Waltz" in a minute; a curiosity only.
  270.     Here is the basic matrix you should remember:
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278. IBM PC Assembly Language Tutorial                                         6
  279.  
  280.  
  281.          Two operands:          One operand:
  282.           R <-- M                R
  283.           M <-- R                M
  284.           R <-- R                S *
  285.           R|M <-- I
  286.           R|M <-- S  *
  287.           S <-- R|M  *
  288.       * -- data moving instructions (MOV, PUSH, POP) only
  289.       S -- segment register (CS, DS, ES, SS)
  290.       R -- ordinary register (AX, BX, CX, DX, SI, DI, BP, SP,
  291.                               AH, AL, BH, BL, CH, CL, DH, DL)
  292.       M -- one of the following
  293.                pure address
  294.                [BX]+offset
  295.                [BP]+offset
  296.                any of the above indexed by SI
  297.                any of the first three indexed by DI
  298. 4.  Of course, you want to learn the operations themselves.  As I've sug-
  299.     gested, you want to learn the op codes as the assembler presents them,
  300.     not as the CPU machine language presents them.  So, even though there
  301.     are many MOV op codes you don't need to learn them.  Basically, here is
  302.     the instruction set:
  303.     a.  Ordinary two operand instructions.  These instructions perform an
  304.         operation and leave the result in place of one of the operands.
  305.         They are
  306.         1)  ADD and ADC -- addition, with or without including a carry from
  307.             a previous addition
  308.         2)  SUB and SBB -- subtraction, with or without including a borrow
  309.             from a previous subtraction
  310.         3)  CMP -- compare.  It is useful to think of this as a subtraction
  311.             with the answer being thrown away and neither operand actually
  312.             changed
  313.         4)  AND, OR, XOR -- typical boolean operations
  314.         5)  TEST -- like an AND, except the answer is thrown away and nei-
  315.             ther operand is changed.
  316.         6)  MOV -- move data from source to target
  317.         7)  LDS, LES, LEA -- some specialized forms of MOV with side
  318.             effects
  319.     b.  Ordinary one operand instructions.  These can take any of the oper-
  320.         and forms described above.  Usually, the perform the operation and
  321.         leave the result in the stated place:
  322.         1)  INC -- increment contents
  323.  
  324. IBM PC Assembly Language Tutorial                                         7
  325.  
  326.  
  327.         2)  DEC -- decrement contents
  328.         3)  NEG -- twos complement
  329.         4)  NOT -- ones complement
  330.         5)  PUSH -- value goes on stack (operand location itself unchanged)
  331.         6)  POP -- value taken from stack, replaces current value
  332.     c.  Now you touch on some instructions which do not follow the general
  333.         operand rules but which require the use of certain registers.  The
  334.         important ones are
  335.         1)  The multiply and divide instructions
  336.         2)  The "adjust" instructions which help in performing arithmetic
  337.             on ASCII or packed decimal data
  338.         3)  The shift and rotate instructions.  These have a restriction on
  339.             the second operand:  it must either be the immediate value 1 or
  340.             the contents of the CL register.
  341.         4)  IN and OUT which send or receive data from one of the 1024
  342.             hardware ports.
  343.         5)  CBW and CWD -- convert byte to word or word to doubleword by
  344.             sign extension
  345.     d.  Flow of control instructions.  These deserve study in themselves
  346.         and we will discuss them a little more.  They include
  347.         1)  CALL, RET -- call and return
  348.         2)  INT, IRET -- interrupt and return-from-interrupt
  349.         3)  JMP -- jump or "branch"
  350.         4)  LOOP, LOOPNZ, LOOPZ -- special (and useful) instructions which
  351.             implement a counted loop similar to the 370 BCT instruction
  352.         5)  various conditional jump instructions
  353.     e.  String instructions.  These implement a limited storage-to-storage
  354.         instruction subset and are quite powerful.  All of them have the
  355.         property that
  356.         1)  The source of data is described by the combination DS and SI.
  357.         2)  The destination of data is described by the combination ES and
  358.             DI.
  359.         3)  As part of the operation, the SI and/or DI register(s) is(are)
  360.             incremented or decremented so the operation can be repeated.
  361.  
  362. IBM PC Assembly Language Tutorial                                         8
  363.  
  364.  
  365.         They include
  366.         1)  CMPSB/CMPSW -- compare byte or word
  367.         2)  LODSB/LODSW -- load byte or word into AL or AX
  368.         3)  STOSB/STOSW -- store byte or word from AL or AX
  369.         4)  MOVSB/MOVSW -- move byte or word
  370.         5)  SCASB/SCASW -- compare byte or word with contents of AL or AX
  371.         6)  REP/REPE/REPNE -- a prefix which can be combined with any of
  372.             the above instructions to make them execute repeatedly across a
  373.             string of data whose length is held in CX.
  374.     f.  Flag instructions: CLI, STI, CLD, STD, CLC, STC.  These can set or
  375.         clear the interrupt (enabled) direction (for string operations) or
  376.         carry flags.
  377.     The addressing summary and the instruction summary given above masks a
  378.     lot of annoying little exceptions.  For example, you can't POP CS, and
  379.     although the R <-- M form of LES is legal, the M <-- R form isn't etc.
  380.     etc.  My advice is
  381.     a.  Go for the general rules
  382.     b.  Don't try to memorize the exceptions
  383.     c.  Rely on common sense and the assembler to teach you about
  384.         exceptions over time.  A lot of the exceptions cover things you
  385.         wouldn't want to do anyway.
  386. 5.  A few instructions are rich enough and useful enough to warrent careful
  387.     study.  Here are a few final study guidelines:
  388.     a.  It is well worth the time learning to use the string instruction
  389.         set effectively.  Among the most useful are
  390.                 REP MOVSB           ;moves a string
  391.                 REP STOSB           ;initializes memory
  392.                 REPNE SCASB         ;look up occurance of character in string
  393.                 REPE CMPSB          ;compare two strings
  394.     b.  Similarly, if you have never written for a stack machine before,
  395.         you will need to exercise PUSH and POP and get very comfortable
  396.         with them because they are going to be good friends.  If you are
  397.         used to the 370, with lots of general purpose registers, you may
  398.         find yourself feeling cramped at first, with many fewer registers
  399.         and many instructions having register restrictions.  But, you have
  400.         a hidden ally:  you need a register and you don't want to throw
  401.         away what's in it?  Just PUSH it, and when you are done, POP it
  402.         back.  This can lead to abuse.  Never have more than two
  403.         "expedient" PUSHes in effect and never leave something PUSHed
  404.         across a major header comment or for more than 15 instructions or
  405. IBM PC Assembly Language Tutorial                                         9
  406.  
  407.