home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / asm_programming / CHAP5.DOC < prev    next >
Text File  |  1990-08-03  |  29KB  |  692 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.           *****************************************************************
  8.                                  REGISTRATION
  9.  
  10.           Hey, Chuck, I'm no chump!
  11.  
  12.           I'm using your programs/manual, and I  want to pay my fair share.
  13.           Please make me a registered user of "The  PC Assembler Tutor" and
  14.           "The PC Assembler  Helper". Enclosed is  a check for $9.95  (plus
  15.           6.5% tax or $10.60 for California residents). Say, that's cheaper
  16.           than a large pizza!
  17.  
  18.  
  19.           Name_________________________________________________________
  20.                     Last                First               Initial
  21.  
  22.           Address______________________________________________________
  23.                     Street Address
  24.  
  25.                  _______________________________________________________
  26.                     City, State, and Zip Code
  27.  
  28.           I got my copy from ___________________________________________
  29.  
  30.           Make checks payable to NELSOFT and send your registration to:
  31.  
  32.                NELSOFT
  33.                P.O. Box 21389
  34.                Oakland, CA  94620
  35.  
  36.           +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  37.                              REGISTRATION BENEFITS
  38.            
  39.           As a  registered user of  "The PC  Assembler Helper" and  "The PC
  40.           Assembler Tutor" you are entitled to:
  41.  
  42.           1) Use asmhelp.obj and helpmem.com for personal use.
  43.           2) Make 1 (one) printer copy of "The PC Assembler Tutor".
  44.           3) Use all programs in "The PC Assembler Tutor" for personal use.
  45.           4) Make an archival copy of the disks.
  46.           5) Distribute UNALTERED disks to friends for their perusal.
  47.           6) Use any updates to either "The PC Assembler Helper" or "The PC
  48.              Assembler Tutor" under the same registration conditions.
  49.  
  50.           Though copies  of  the disk  may be  given away  if  there is  no
  51.           charge, it is illegal to charge for redistribution of the disk or
  52.           its  contents  without   permission  of  the  author.   Under  no
  53.           circumstances  may  you  distribute  printed  copies of  "The  PC
  54.           Assembler  Tutor". If you  intend to charge  for distributing the
  55.           disk or its  information, please read  and sign the  distribution
  56.           agreement which is in INTRO1.DOC.
  57.  
  58.           *****************************************************************
  59.  
  60.  
  61.  
  62.                                                                             31
  63.  
  64.                             CHAPTER 5 - ADDITION AND SUBTRACTION
  65.  
  66.  
  67.              The first arithmetic operations we will look at are addition and
  68.              subtraction, but before we do that, we need to look at one
  69.              instruction that controls program flow.
  70.  
  71.              LOOP
  72.  
  73.              We already have JMP which sends you to a label:
  74.  
  75.                  jmp  label3
  76.  
  77.              sends the program to label3, wherever that is in the code.
  78.              Sometimes we want to repeat a section of code a specific number
  79.              of times and then go on. For this, we have LOOP. LOOP decrements
  80.              the CX register by 1. If CX is not zero after being decremented,
  81.              LOOP jumps to the label indicated. If CX is zero after being
  82.              decremented, LOOP falls through. 
  83.  
  84.              The 8086 does not have general purpose registers. A general
  85.              purpose register is a register that can be used for ALL
  86.              instructions. There are a number of instructions on the 8086
  87.              which must be done with specific registers, and LOOP is the first
  88.              one we meet. LOOP always looks at the CX register.
  89.  
  90.  
  91.              This first program lets you enter a number and then loops that
  92.              many times so you can watch the CX register. As usual, you exit
  93.              the program by hitting Control-C. We use temp2.asm.
  94.  
  95.              temp2.asm
  96.              ; - - - - START CODE BELOW THIS LINE
  97.                  call show_regs      ; initialize
  98.  
  99.              outer_loop:
  100.                  call get_unsigned
  101.                  mov  cx, ax         ; number to cx
  102.  
  103.              inner_loop:
  104.                  call show_regs_and_wait
  105.                  loop inner_loop
  106.  
  107.                  jmp  outer_loop
  108.  
  109.              ; - - - - END CODE ABOVE THIS LINE
  110.  
  111.              A very simple program. As always, link it with asmhelp.obj.
  112.              Get_unsigned gets a two byte number (less than 65536) and puts it
  113.              in AX. We put that number in CX, and then watch the program loop.
  114.              Make sure you use show_regs_and_wait, or everything will happen
  115.              too fast for you to see. Try entering 0. On the first pass, loop
  116.              will decrement CX from 0 to 65535. If CX is 0 when you enter, you
  117.  
  118.              ______________________
  119.  
  120.              The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
  121.  
  122.  
  123.  
  124.  
  125.              The PC Assembler Tutor                                         32
  126.              ______________________
  127.  
  128.              have to repeat the loop 65536 times before you exit the loop. Hit
  129.              Control-C now to exit. 
  130.  
  131.              Throughout the book, I will use label names that end in '_loop'
  132.              to indicate that they are the destination of a jump or loop
  133.              instruction. The single word "loop" is a reserved word and may
  134.              not be used as a label - it can only be used as an instruction.
  135.  
  136.              The addition program will have 4 sections and LOOP will give us
  137.              the ability to do each section a limited number of times before
  138.              going on to the next section.
  139.  
  140.  
  141.              ADDITION
  142.  
  143.              If you read the introductory section on numbers carefully, you
  144.              know that it is the same instruction for both signed and unsigned
  145.              addition. The 8086 sets the flags correctly for both signed and
  146.              unsigned addition. For signed addition, the following flags are
  147.              set:
  148.  
  149.                  OF   the overflow flag is set (1) if the result is too
  150.                  negative or too positive, that is, if the result in the
  151.                  register does not show the correct result of the addition.
  152.                  It is cleared (0) otherwise.
  153.  
  154.                  ZF   the zero flag is 1 if the result is zero, and is
  155.                  cleared (0) if the result is non-zero.
  156.  
  157.                  SF   the sign flag is set (1) if the result is NEGATIVE and
  158.                  is cleared (0) if the result is POSITIVE. Zero is considered
  159.                  a positive number.
  160.  
  161.              For unsigned addition, the following flags are set:
  162.  
  163.                  CF   the carry flag is set (1) if the result is too large
  164.                  (over 255 for byte and over 65535 for word operations). It
  165.                  is cleared (0) otherwise.
  166.  
  167.                  ZF   the zero flag is the same as above.
  168.  
  169.              In addition, there are two more flags (PF the parity flag and AF
  170.              the auxillary flag) which will be set or cleared; we will learn
  171.              about them later. 
  172.  
  173.              Show_regs shows all the flags. The setting for each flag is
  174.              underneath its name. For the flags OF, ZF and CF, there is an 'X'
  175.              if the flag is set and a blank if the flag is cleared. SF, the
  176.              sign flag, is '-' if the flag is set and '+' if the flag is
  177.              cleared. 
  178.  
  179.              The addition program is fairly long because there are four things
  180.              to look at - unsigned word addition, unsigned byte addition,
  181.              signed word addition and signed byte addition. For that reason,
  182.              it has already been typed in for you. It is called ADD1.ASM and
  183.              its pathname is \XTRAFILE\ADD1.ASM. Print out a copy of it.
  184.  
  185.  
  186.  
  187.  
  188.  
  189.              Chapter 5 - Addition and Subtraction                           33
  190.              ____________________________________
  191.  
  192.              There are four blocks of code which are almost identical except
  193.              the calls are a little different and two blocks refer to whole
  194.              registers while the other two refer to half registers. At the
  195.              head of each block is code to set the appropriate register styles
  196.              for show_regs. SI, DI, and BP are not used and are set to 0 to
  197.              make the screen easier to read. Here is the first block of code,
  198.              which is typical.
  199.  
  200.              ; - - - CODE
  201.                     ; UNSIGNED WORD ADDITION 
  202.                     mov   ax_byte, 2          ; ax, bx, dx unsigned 
  203.                     mov   bx_byte, 2 
  204.                     mov   dx_byte, 2 
  205.                     lea   ax, ax_byte         ; call set_reg_style 
  206.                     call  set_reg_style 
  207.               
  208.                     mov   cx, 3               ; 3 iterations 
  209.              unsigned_loop: 
  210.                     mov   ax, 0      ; clear the registers for visibility
  211.                     mov   bx, 0 
  212.                     mov   dx, 0 
  213.                     call  show_regs 
  214.                     call  get_unsigned        ; first number to  ax 
  215.                     call  show_regs 
  216.                     push  ax                  ; temporarily save ax 
  217.                     call  get_unsigned        ; second number to bx 
  218.                     mov   bx, ax 
  219.                     pop   ax                  ; get ax back 
  220.                     mov   dx, ax              ; copy of ax to dx 
  221.                     add   dx, bx              ; dx (=ax) + bx 
  222.                     call  show_regs_and_wait 
  223.                     loop  unsigned_loop 
  224.  
  225.              ; - - - CODE
  226.  
  227.              First, we set AX, BX, and DX for the appropriate register style.
  228.              Here it is unsigned full register. We then put 3 in CX so we can
  229.              have 3 iterations with loop. Upon entering the loop, AX, BX, and
  230.              DX are cleared for reasons of visibility. We don't want the
  231.              screen cluttered up with numbers. Get_unsigned gets a two byte
  232.              unsigned number and returns it in AX. We want the first number to
  233.              be visually on the top (which is AX), but there is a problem
  234.              here. In order to get the second number we need to call
  235.              get_unsigned again, and it is going to put another number in AX.
  236.              We need to temporarily store the first number while we bring in
  237.              the second number and transfer it to bx. 
  238.  
  239.              There is a special 8086 instruction to do this, it is called
  240.              PUSH. Push temporarily stores a word. The word can be either a
  241.              full register or a word (two bytes) in memory. You can have
  242.              either:
  243.  
  244.                  variable1 dw   10000
  245.  
  246.                       push ax
  247.                       push variable1
  248.  
  249.  
  250.  
  251.  
  252.  
  253.              The PC Assembler Tutor                                         34
  254.              ______________________
  255.  
  256.              These are stored in a special place called the stack which we
  257.              will talk about much later. When you want it back, you use the
  258.              instruction POP. POP gets back the LAST thing that you pushed
  259.              onto the stack. Things come off the stack in REVERSE order of how
  260.              they were put on.
  261.  
  262.                  push variable1
  263.                  push variable2
  264.                  push variable3
  265.                  push variable4
  266.                  pop  variable4
  267.                  pop  variable3
  268.                  pop  variable2
  269.                  pop  variable1
  270.  
  271.              is the correct order. This is used for temporary storage only,
  272.              and the only thing which is accessable is the last thing which
  273.              you PUSHed on the stack.
  274.  
  275.              We push AX to store it temporarily, call get_unsigned again and
  276.              transfer the number to BX. We then pop AX to get the number back.
  277.              The situation now is: the first number is in AX, the second
  278.              number is in BX. For the actual addition, we transfer AX to DX
  279.              and then add DX and BX. AX and BX contain the two numbers, and DX
  280.              contains the result. Then you must press ENTER to continue. LOOP
  281.              will jump to 'unsigned_loop' two times. The third time it will
  282.              fall through to the next section of code. 
  283.  
  284.              This program illustrates a hallmark of assembler code. It
  285.              normally takes scads of code just to do something simple.
  286.  
  287.              Assemble add1.asm and link it with asmhelp.obj. Run it:
  288.  
  289.              ******************** SCREEN SHOT ******************************
  290.  
  291.                  AX  17428                             SI  00000
  292.                  BX  19755                             DI  00000
  293.                  CX  00003                             BP  00000
  294.                  DX  37183                             SP  00508
  295.  
  296.                  CS  0AA5H   DS  0A55H   ES  0A25H   SS  0A35H   IP  004DH
  297.  
  298.                  OF   DF  IEF   TF   SF   ZF   AF   PF   CF
  299.                   x    +    x         -              E           COUNT  00004
  300.              ----------------------------------------------------------------
  301.  
  302.              The PC Assembler Helper   Version 1.0
  303.              Copyright (C) 1989  Chuck Nelson   All rights reserved.
  304.              Enter a number from 0 to 65535  17428
  305.              Enter a number from 0 to 65535  19755
  306.              Press ENTER to continue
  307.  
  308.              *****************************************************************
  309.  
  310.              This is the screen after the first addition. I have added 17428
  311.              (AX) and 19755 (BX). The result 37183 is in DX. CX is still 3
  312.              because it hasn't LOOPed yet.
  313.  
  314.  
  315.  
  316.  
  317.              Chapter 5 - Addition and Subtraction                           35
  318.              ____________________________________
  319.  
  320.  
  321.              Notice that even though it is the same assembler instruction:
  322.  
  323.                  add
  324.  
  325.              in all four blocks of code, it is doing both signed and unsigned
  326.              addition correctly. When you are doing signed addition, you want
  327.              to look at OF, the overflow flag, SF, the sign flag, and ZF, the
  328.              zero flag after each addition to see how they are set. When you
  329.              do unsigned addition, you want to look at CF, the carry flag, and
  330.              ZF, the zero flag to see how they are set. Play around with this
  331.              for a while, and then it is time for the next program.
  332.  
  333.              As in all 8086 instructions, the order is:
  334.  
  335.                  add  destination, source
  336.  
  337.              We add both numbers, and put the result in the destination, the
  338.              thing on the left.
  339.  
  340.  
  341.              There are five different types of addition you can do, (just as
  342.              there are five different types of moves). They are:
  343.  
  344.                  1. add two registers
  345.                  2. add a register to a variable (memory)
  346.                  3. add a variable (memory) to a register
  347.                  4. add a constant to a variable (memory)
  348.                  5. add a constant to a register
  349.  
  350.              Here's a program that does all 5 things. Use template.asm to make
  351.              this program. template.asm is almost the same as the other ones
  352.              we have used. It has a few changes. First, it now lists ALL the
  353.              subroutines you can call in asmhelp.obj.{1} Appendix 1
  354.              (\APPENDIX\APP1.DOC) contains a description of all the
  355.              subroutines, what they do, and how they are called. Second, the
  356.              size of STACKSEG is larger. We don't need this large of a stack
  357.              now; it is for later. Finally, there is a section:
  358.  
  359.              ; + + + + + + + + + + PUT SUBROUTINES BELOW THIS LINE 
  360.  
  361.              ; + + + + + + + + + + PUT SUBROUTINES ABOVE THIS LINE 
  362.  
  363.              for subroutines. Ignore this. This is for later. 
  364.  
  365.  
  366.              From now on, we will always use template.asm unless it is
  367.              explicitly stated that something else is being used. Here's the
  368.              program:
  369.  
  370.              template.asm
  371.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  372.              ____________________
  373.  
  374.                 1 This does not change the size of the .EXE file by even
  375.              one byte, but it adds a lot of information to the .OBJ file, so
  376.              they are much larger.
  377.  
  378.  
  379.  
  380.  
  381.              The PC Assembler Tutor                                         36
  382.              ______________________
  383.  
  384.              variable1    dw     ? 
  385.              variable2    dw     ? 
  386.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  387.               
  388.              ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE 
  389.                     call  show_regs 
  390.              outer_loop: 
  391.                     call  get_unsigned        ; first number to ax 
  392.                     push  ax                  ; store ax 
  393.                     call  get_unsigned        ; second number to bx 
  394.                     mov   bx, ax               
  395.                     pop   ax                  ; restore ax 
  396.                     mov   variable1, ax       ; first number to variable1 
  397.                     mov   variable2, bx       ; second number to variable2 
  398.                     ; add 2 registers 
  399.                     mov   cx, ax              ; cx + bx 
  400.                     add   cx, bx 
  401.                     ; add register to memory 
  402.                     add   variable1, bx 
  403.                     mov   dx, variable1       ; put in dx for display 
  404.                     ; add memory to register 
  405.                     mov   si, ax 
  406.                     add   si, variable2 
  407.                     ; add a constant to memory 
  408.                     add   variable2, 25 
  409.                     mov   di, variable2       ; put in di for display 
  410.                     ; add a constant to a register 
  411.                     mov   bp, bx 
  412.                     add   bp, 25 
  413.                     call show_regs 
  414.                     jmp   outer_loop 
  415.               
  416.              ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE 
  417.  
  418.  
  419.              The program puts the first number in AX and the second number in
  420.              BX. It then proceeds to do the same addition (first number plus
  421.              second number) three times. These are:
  422.  
  423.                  1. CX = add two registers (CX + BX)
  424.                  2. DX = add a register to memory (variable1 + BX)
  425.                  3. SI = add memory to a register (SI + variable2)
  426.  
  427.              Finally it adds a constant (second number + 25). These are:
  428.  
  429.                  4. DI = add a constant to memory (variable2 + 25)
  430.                  5. BP = add a constant to a register (BP + 25)     
  431.  
  432.  
  433.              On the 8086, it is not possible to add two things in memory. That
  434.              is:
  435.  
  436.                  add  variable1, variable2
  437.  
  438.              is an illegal instruction. Instead, you need to write:
  439.  
  440.                  mov  ax, variable2
  441.  
  442.  
  443.  
  444.  
  445.              Chapter 5 - Addition and Subtraction                           37
  446.              ____________________________________
  447.  
  448.                  add  variable1, ax 
  449.  
  450.  
  451.              SUBTRACTION
  452.  
  453.              It is now time to do some subtraction. The instruction is SUB:
  454.  
  455.                  sub  destination, source
  456.  
  457.              subtracts source from destination and stores it in destination,
  458.              the thing on the left.
  459.  
  460.                  sub  ax, cx         ; (ax - cx) -> ax
  461.  
  462.              In order to do subtraction we are going to modify add1.asm, so
  463.              make a copy and call it sub1.asm:
  464.  
  465.                  >copy  add1.asm  sub1.asm
  466.  
  467.              How many instructions do we need to change to modify the program?
  468.              Four.
  469.  
  470.                  add  dx, bx    ->        sub  dx, bx
  471.                  add  dl, bl    ->        sub  dl, bl
  472.  
  473.              Each of these is changed twice, and we are ready to roll.
  474.              Assemble it, link it, and run it. Once again we want to look at
  475.              the flags at the end of each subtraction. For unsigned
  476.              subtraction, look at ZF, the zero flag, and CF, the carry flag.
  477.              This time, CF will be set if the result is below zero. For signed
  478.              subtraction, look at OF, the overflow flag, SF, the sign flag,
  479.              and ZF, the zero flag. As with addition, subtraction changes PF,
  480.              the parity flag and AF the auxillary flag. They don't concern us.
  481.  
  482.              As with addition, there are five possibilities for subtraction.
  483.              They are:
  484.  
  485.                  1. subtract one register from another
  486.                  2. subtract a register from a variable (memory)
  487.                  3. subtract a variable (memory) from a register
  488.                  4. subtract a constant from a variable (memory)
  489.                  5. subtract a constant from a register
  490.  
  491.              the code for these is:
  492.  
  493.                  sub  cx, bx         ; (cx - bx)         ->   cx
  494.                  sub  variable1, bx  ; (variable1 - bx)  ->   variable1
  495.                  sub  si, variable2  ; (si - variable2)  ->   si
  496.                  sub  variable2, 25  ; (variable2 - 25)  ->   variable2
  497.                  sub  bp, 25         ; (bp - 25)         ->   bp
  498.  
  499.              You can copy add2.asm to sub2.asm if you want and change the five
  500.              ADD instructions to SUB instructions. It will then do those five
  501.              types of subtraction. 
  502.  
  503.  
  504.  
  505.  
  506.  
  507.              The PC Assembler Tutor                                         38
  508.              ______________________
  509.  
  510.              SIGNED AND UNSIGNED NUMBERS
  511.  
  512.              What should you do if you are doing unsigned addition or
  513.              subtraction and the carry flag gets set? It depends. Sometimes it
  514.              makes a difference, sometimes it doesn't. If you have an error
  515.              handling routine, then you can call it with the following code:
  516.  
  517.                       add  ax, bx
  518.                       jnc  go_on
  519.                       call error_handler
  520.                  go_on:
  521.  
  522.              JC and JNC are conditional jump instructions. JC (jump on carry)
  523.              jumps if the carry flag is set (1) and JNC (jump on not carry)
  524.              jumps if the carry flag is not set (0). Using reverse logic here,
  525.              we skip the error handler if everything is ok.
  526.  
  527.              For signed numbers, it is certainly an error if there is
  528.              overflow. You are making mathematical calculations and you now
  529.              have invalid data. One possibility is to do the same as above but
  530.              with the overflow flag.
  531.  
  532.                       add  ax, bx
  533.                       jno  go_on
  534.                       call error_handler
  535.                  go_on:
  536.  
  537.              JO and JNO are two more conditional jump instructions.  JO (jump
  538.              on overflow) jumps if the overflow flag is set (1) and JNO (jump
  539.              on not overflow) jumps if the overflow flag is not set (0). We
  540.              use the same logic here. 
  541.  
  542.              However, there is one special instruction for signed numbers, and
  543.              that is INTO (interrupt on overflow). It is possible to have an
  544.              error handler external to your program. It sits permanantly in
  545.              memory. When you make a signed arithmetic error, INTO interrupts
  546.              your program and goes to the external error handler. The code
  547.              looks like this:
  548.  
  549.                  add  ax, bx
  550.                  into
  551.  
  552.              You probably don't have an error handler in your computer right
  553.              now. In that case, INTO simply goes looking for it and returns
  554.              when it can't find it.
  555.  
  556.              Let's find out if you have an error handler installed. Once
  557.              again, use template.asm
  558.  
  559.              ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE 
  560.                     mov   ax_byte, 1          ; signed register style  
  561.                     mov   bx_byte, 1 
  562.                     mov   cx_byte, 1 
  563.                     lea   ax, ax_byte 
  564.                     call  set_reg_style 
  565.                     call  show_regs 
  566.  
  567.  
  568.  
  569.              Chapter 5 - Addition and Subtraction                           39
  570.              ____________________________________
  571.  
  572.              outer_loop: 
  573.                     call  get_signed 
  574.                     push  ax 
  575.                     call  get_signed 
  576.                     mov   bx, ax 
  577.                     pop   ax 
  578.                     mov   cx, ax 
  579.                     add   cx, bx 
  580.                     into 
  581.                     call  show_regs 
  582.                     jmp   outer_loop 
  583.              ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE 
  584.  
  585.              This is basically the same thing as before, but using AX, BX, and
  586.              CX. They are set for signed style, and then we  get two signed
  587.              numbers and add them. The result is in CX. Right after the
  588.              addition instruction is INTO. If the result is too positive or
  589.              too negative, OF will be set and INTO will look for the error
  590.              handler. 
  591.  
  592.              Assemble this program and link it with asmhelp.obj. Try both
  593.              numbers that do not set the overflow flag and numbers that do set
  594.              the overflow flag. Did anything different happen when the
  595.              overflow flag was set? If nothing different happened, you don't
  596.              have an error handler for INTO. 
  597.  
  598.              Included on the disks is an error handler. It is called INTO.COM,
  599.              and it's pathname is \XTRAFILE\INTO.COM. When you run it:
  600.  
  601.                  >into
  602.  
  603.              it will install itself and then return to the command prompt:
  604.  
  605.                  >
  606.  
  607.              INTO.COM will stay in memory until you reboot or shut off the
  608.              machine. INTO.COM provides the type of sophisticated error
  609.              handling that you might want to use in a real program. Install
  610.              (run) INTO.COM, and then try the previous program again, both
  611.              with numbers that cause an overflow and numbers that don't cause
  612.              an overflow.
  613.  
  614.  
  615.  
  616.  
  617.  
  618.  
  619.  
  620.  
  621.  
  622.  
  623.  
  624.  
  625.  
  626.  
  627.  
  628.  
  629.  
  630.  
  631.              The PC Assembler Tutor                                         40
  632.              ______________________
  633.  
  634.                                           SUMMARY
  635.  
  636.  
  637.              ADD performs both signed and unsigned addition. It can:
  638.  
  639.                  1. add two registers
  640.                  2. add a register to a variable (memory)
  641.                  3. add a variable (memory) to a register
  642.                  4. add a constant to a variable (memory)
  643.                  5. add a constant to a register
  644.  
  645.  
  646.              SUB performs both signed and unsigned subtraction. It can:
  647.  
  648.                  1. subtract one register from another
  649.                  2. subtract a register from a variable (memory)
  650.                  3. subtract a variable (memory) from a register
  651.                  4. subtract a constant from a variable (memory)
  652.                  5. subtract a constant from a register
  653.  
  654.  
  655.              The flags affected by both ADD and SUB are:
  656.  
  657.                  CF   the carry flag (for unsigned). Set if the 0/65535
  658.                  (0/255) border was crossed.
  659.  
  660.                  ZF   the zero flag (for signed and unsigned). Set if the
  661.                  result is 0.
  662.  
  663.                  SF   the sign flag (for signed). Set if the result is
  664.                  negative.
  665.  
  666.                  OF   the overflow flag (for signed). Set if the result was
  667.                  too negative or too positive.
  668.  
  669.                  PF   the parity flag and AF, the auxillary flag
  670.  
  671.              The following jump instructions are conditional on the setting of
  672.              the flags:
  673.  
  674.                  JC   jump on carry, JNC, jump on not carry
  675.                  JO   jump on overflow. JNO, jump on not overflow
  676.  
  677.              LOOP
  678.                  LOOP decrements cx by 1. If cx is then not zero, it jumps to
  679.                  the named label. If cx is zero, it falls through to the next
  680.                  instruction.
  681.  
  682.              INTO
  683.                  If the overflow flag is set, INTO (interrupt on overflow)
  684.                  interrupts the program and goes to an external error handler
  685.                  if one exists. It returns immediately if one doesn't exist.
  686.  
  687.              PUSH and POP
  688.                  PUSH stores either a register or a word (in memory) in a
  689.                  temporary storage area. POP retrieves the last word PUSHed.
  690.  
  691. 
  692.