home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / asm_programming / CHAP15-1.DOC < prev    next >
Text File  |  1990-07-19  |  30KB  |  705 lines

  1.  
  2.  
  3.  
  4.                                                                            137
  5.  
  6.                                 CHAPTER 15 - SUBROUTINES
  7.  
  8.  
  9.              It is now time to talk about subroutines. If you have only used
  10.              BASIC this may be difficult for you. It is assumed that you are
  11.              familiar with subroutines and use them constantly in your
  12.              programming.
  13.  
  14.              You have been using subroutines since the very first program in
  15.              this manual. When you wrote:
  16.  
  17.                  call get_num
  18.  
  19.              you called a subroutine in ASMHELP.OBJ. Now you are going to
  20.              write subroutines yourself and have them call each other. There
  21.              are different template files for programs with subroutines. They
  22.              are SUBTEMP1.ASM and SUBTEMP2.ASM. We will start with SUBTEMP1.
  23.              It has the entry subroutine and a space for additional
  24.              subroutines. The entry subroutine is the subroutine where the
  25.              operating system starts the program; it does the necessary
  26.              initialization and has special code for that. 
  27.  
  28.              You will see some additions to the normal template file. At the
  29.              top is the line:
  30.  
  31.                  INCLUDE      \pushregs.mac 
  32.  
  33.              What this is will be explained later, but you must put the file
  34.              PUSHREGS.MAC in the root directory of your current drive. You
  35.              will find it in the \TEMPLATE subdirectory.
  36.  
  37.              At the end of the SUBTEMP1.ASM is:
  38.  
  39.              ; + + + + + + + + + + + + START SUBROUTINES BELOW THIS LINE 
  40.  
  41.              ; + + + + + + + + + + + + END SUBROUTINES ABOVE THIS LINE 
  42.  
  43.              This is where you will write all the subroutines except the entry
  44.              subroutine which is still the same as before. All data for all
  45.              subroutines still goes in the DATASTUFF segment.
  46.  
  47.  
  48.              Our first program will just call subroutines which will print out
  49.              messages. Using SUBTEMP1.ASM, it looks like this:
  50.  
  51.              ;prog1.asm
  52.  
  53.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  54.              main_message  db   "This is the entry routine.", 0 
  55.              sub1_message  db   "This is subroutine1.", 0 
  56.              sub2_message  db   "This is subroutine2.", 0 
  57.              sub3_message  db   "This is subroutine 3.", 0 
  58.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  59.  
  60.  
  61.              ______________________
  62.  
  63.              The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
  64.  
  65.  
  66.  
  67.  
  68.              The PC Assembler Tutor                                        138
  69.              ______________________
  70.  
  71.              ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE 
  72.                     mov   ax, offset main_message 
  73.                     call  print_string 
  74.                     call  sub1 
  75.                     mov   ax, offset main_message 
  76.                     call  print_string 
  77.              ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE 
  78.  
  79.              ; + + + + + + + + + + + + START SUBROUTINES BELOW THIS LINE 
  80.              ;------------ 
  81.              sub1  proc near 
  82.               
  83.                     push  ax 
  84.                     mov   ax, offset sub1_message 
  85.                     call  print_string 
  86.                     call  sub2 
  87.                     mov   ax, offset sub1_message 
  88.                     call  print_string 
  89.                     pop   ax 
  90.               
  91.                     ret 
  92.               
  93.              sub1   endp 
  94.              ;------------ 
  95.              sub2  proc near 
  96.               
  97.                     push  ax 
  98.                     mov   ax, offset sub2_message 
  99.                     call  print_string 
  100.                     call  sub3 
  101.                     mov   ax, offset sub2_message 
  102.                     call  print_string 
  103.                     pop   ax 
  104.               
  105.                     ret 
  106.               
  107.              sub2   endp 
  108.              ;------------ 
  109.              sub3  proc near 
  110.               
  111.                     push  ax 
  112.                     mov   ax, offset sub3_message 
  113.                     call  print_string 
  114.                     pop   ax 
  115.               
  116.                     ret 
  117.               
  118.              sub3   endp 
  119.              ; ---------- 
  120.              ; + + + + + + + + + + + + END SUBROUTINES ABOVE THIS LINE 
  121.  
  122.              The data consists of messages to be printed by print_string.
  123.              Print_string prints a zero terminated string (the number zero,
  124.              not the character '0'), so there must be a zero after each
  125.              message in the data segment. The entry subroutine prints a
  126.              message and then calls sub1, the first subroutine, which prints a
  127.              message and calls sub2 which prints a message and calls sub3.
  128.  
  129.  
  130.  
  131.  
  132.              Chapter 15 - Subroutines                                      139
  133.              ________________________
  134.  
  135.              Sub3 prints a message and then returns to sub2 which prints a
  136.              message and returns to sub1 which prints a message and returns to
  137.              the entry routine which prints a message and then exits. This
  138.              program should print 7 messages in all. You will notice that the
  139.              first thing that each subroutine does is save the value in AX,
  140.              since it uses the AX register. This is the cardinal rule of
  141.              robustness at the assembler level.
  142.  
  143.                  IF YOU USE A REGISTER, YOU MUST SAVE ITS VALUE BY PUSHING IT
  144.                  ON THE STACK; YOU MUST THEN RESTORE THE VALUE JUST BEFORE
  145.                  EXITING.
  146.  
  147.              It is impossible to overstress this. The routines which call your
  148.              routine might rely on the registers remaining unaltered. If you
  149.              disobey this rule and alter the registers, you'll be sorry.
  150.  
  151.              Why doesn't the entry routine push and pop the registers it uses?
  152.              Well, the operating system assumes the registers will contain
  153.              trash upon return from the program, so it uses nothing in the
  154.              data registers. 
  155.  
  156.              All the subroutines except the entry routine are near routines.
  157.              We will only use near routines. Assemble this program, link it
  158.              and run it. If it works ok, it is then time for program 2, which
  159.              is the same as program1, but is in two files.
  160.  
  161.              Often, we want parts of a program in different files. Perhaps
  162.              parts are standard subprograms which you have already written and
  163.              assembled, perhaps the total program is too large to be handled
  164.              comfortably in one file, perhaps different people are writing
  165.              different parts of the program. Not only must we write the
  166.              programs, but we must be able to connect them. We will put the
  167.              entry routine, sub2 and the associated data in subtemp1.asm. We
  168.              will put sub1, sub3, and the associated data in subtemp2.asm.
  169.  
  170.              Take a look at SUBTEMP2.ASM. It is slightly different. First, it
  171.              does not have the variables that you need for set_reg_style
  172.              (ax_byte, bx_byte, etc.) but it does have EXTRN statements for
  173.              them. This means that you can change the register style from this
  174.              file. SUBTEMP1.ASM has these variables declared PUBLIC so the
  175.              linker can join them correctly.{1} We will talk about the correct
  176.              way to declare external data later.
  177.  
  178.              SUBTEMP2.ASM has no stack segment, though there could be one.
  179.              There is no entry subroutine. Therefore at the very end, you have
  180.              the line:
  181.  
  182.                  END
  183.  
  184.              with nothing after it. In SUBTEMP1.ASM, you have
  185.              ____________________
  186.  
  187.                 1. The reason for having only one set of variables for the
  188.              style is so that every time you change one of the style
  189.              variables, the array is updated. If you had two different arrays
  190.              you could have two different sets of information for
  191.              set_reg_style.
  192.  
  193.  
  194.  
  195.  
  196.              The PC Assembler Tutor                                        140
  197.              ______________________
  198.  
  199.  
  200.                  END  start
  201.  
  202.              so the assembler and linker know that the program begins at the
  203.              label "start".
  204.  
  205.              Let's do the two programs. Here are the data, the entry code and
  206.              the subroutine code from the first file.
  207.  
  208.              ;prog1.asm
  209.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  210.              main_message  db   "This is the entry routine.", 0 
  211.              sub2_message  db   "This is subroutine2.", 0 
  212.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  213.               
  214.              ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE 
  215.              PUBLIC sub2 
  216.              EXTRN  sub1:NEAR, sub3:NEAR 
  217.               
  218.                     mov   ax, offset main_message 
  219.                     call  print_string 
  220.                     call  sub1 
  221.                     mov   ax, offset main_message 
  222.                     call  print_string 
  223.              ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE 
  224.  
  225.              ; + + + + + + + + + + + + START SUBROUTINES BELOW THIS LINE 
  226.              sub2  proc near 
  227.               
  228.                     push  ax 
  229.                     mov   ax, offset sub2_message 
  230.                     call  print_string 
  231.                     call  sub3 
  232.                     mov   ax, offset sub2_message 
  233.                     call  print_string 
  234.                     pop   ax 
  235.               
  236.                     ret 
  237.               
  238.              sub2   endp 
  239.              ; + + + + + + + + + + + + END SUBROUTINES ABOVE THIS LINE 
  240.  
  241.              Notice that sub1 and sub3 have been declared EXTRN before they
  242.              were referenced, and the EXTRN statement tells the assembler that
  243.              they are both near procedures. sub2 has been declared PUBLIC so
  244.              the assembler will give the address of sub2 to the linker.
  245.  
  246.              Here's the data and code for the other file.
  247.  
  248.              ;prog2.asm
  249.  
  250.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  251.              sub1_message  db   "This is subroutine1.", 0 
  252.              sub3_message  db   "This is subroutine 3.", 0 
  253.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  254.                
  255.              ; + + + + + + + + + + + + START SUBROUTINES BELOW THIS LINE 
  256.  
  257.  
  258.  
  259.  
  260.              Chapter 15 - Subroutines                                      141
  261.              ________________________
  262.  
  263.              PUBLIC sub1, sub3 
  264.              EXTRN  sub2:NEAR 
  265.              ;------------ 
  266.              sub1  proc near 
  267.               
  268.                     push  ax 
  269.                     mov   ax, offset sub1_message 
  270.                     call  print_string 
  271.                     call  sub2 
  272.                     mov   ax, offset sub1_message 
  273.                     call  print_string 
  274.                     pop   ax 
  275.               
  276.                     ret 
  277.               
  278.              sub1   endp 
  279.              ;------------ 
  280.              sub3  proc near 
  281.               
  282.                     push  ax 
  283.                     mov   ax, offset sub3_message 
  284.                     call  print_string 
  285.                     pop   ax 
  286.               
  287.                     ret 
  288.               
  289.              sub3   endp 
  290.              ; ---------- 
  291.              ; + + + + + + + + + + + + END SUBROUTINES ABOVE THIS LINE 
  292.  
  293.              Here sub1 and sub3 have been declared PUBLIC and sub2 has been
  294.              declared EXTRN.
  295.  
  296.              Assemble both programs and then link all three.
  297.  
  298.                  link prog1+prog2+\asmhelp.obj 
  299.  
  300.              assuming that asmhelp is in the root directory. Run it. You
  301.              should have the same results as before. 
  302.  
  303.              We are going to do one more thing with the same two files.
  304.              Without changing any of the code, we are going to put the data
  305.              for prog1 in prog2 and the data for prog2 in prog1 like this.
  306.  
  307.              ;prog1
  308.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  309.              sub1_message  db   "This is subroutine1.", 0 
  310.              sub3_message  db   "This is subroutine 3.", 0 
  311.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  312.  
  313.              ;prog2
  314.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  315.              main_message  db   "This is the entry routine.", 0 
  316.              sub2_message  db   "This is subroutine2.", 0 
  317.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  318.  
  319.              So far, so good. Obviously we are going to need some more PUBLIC
  320.  
  321.  
  322.  
  323.  
  324.              The PC Assembler Tutor                                        142
  325.              ______________________
  326.  
  327.              statements and some EXTRN statements so the linker can link the
  328.              four messages, but where do they go and what do they look like?
  329.              The PUBLIC statements are the easiest. Put them in the segment
  330.              where the message data appears, either before or after the data
  331.              declaration.
  332.  
  333.              The EXTRN statement is a little more complicated. First, all data
  334.              is declared EXTRN by giving the variable name followed by a colon
  335.              followed by its data type. The data types are BYTE, WORD, DWORD
  336.              (4bytes), QWORD (quadword or 8 bytes), and TBYTE (10 bytes).
  337.              These are the standard 8086/7 data sizes. Therefore we have:
  338.  
  339.                  EXTRN sub1_message:BYTE, sub3_message:BYTE
  340.  
  341.              in prog2.asm and:
  342.  
  343.                  EXTRN main_message:BYTE, sub2_message:BYTE
  344.  
  345.              in prog1.asm. Where do they go? In order to know that, we need to
  346.              talk about segment overrides again. 
  347.  
  348.              You will remember from our discussion of the ASSUME statement
  349.              that every time the assembler writes code with a variable, it
  350.              checks the ASSUME statements to see which segment register(s)
  351.              have the address of the segment that that variable is in. If we
  352.              have:
  353.  
  354.                  ASSUME cs:SEG1, ds:SEG2, es:SEG3, ss:SEG4
  355.  
  356.              then if variable1 is in SEG2, the assembler will write no
  357.              override in the code since DS is the 8086 default segment.
  358.  
  359.                  MACHINE CODE             ASSEMBLER INSTRUCTION
  360.                     A1 0000                 mov   ax, variable1 
  361.  
  362.              If variable1 is in SEG1 or SEG3 or SEG4, the assembler will write
  363.              the appropriate segment override in the code.
  364.  
  365.                     MACHINE CODE               ASSEMBLER INSTRUCTION
  366.                                  
  367.                     2E: A1 0000                  mov   ax, variable1 
  368.                     26: A1 0000                  mov   ax, variable1 
  369.                     36: A1 0000                  mov   ax, variable1 
  370.  
  371.              (By the way, those zeros just mean that the variable is at 0000
  372.              offset from the beginning of the segment).
  373.  
  374.              The same thing happens when you have an EXTRN statement. The
  375.              assembler associates the externally declared variable with the
  376.              segment it is declared in. When the variable is used, it then
  377.              goes through the same actions as if the variable were actually in
  378.              that segment. Let's declare variable5 external with:
  379.  
  380.                  EXTRN variable5:WORD
  381.  
  382.              If we have:
  383.  
  384.  
  385.  
  386.  
  387.  
  388.              Chapter 15 - Subroutines                                      143
  389.              ________________________
  390.  
  391.                  ASSUME cs:SEG1, ds:SEG2, es:SEG3, ss:SEG4
  392.  
  393.              then if variable5 is declared external in SEG2, the assembler
  394.              will write no override in the code since DS is the 8086 default
  395.              segment.
  396.  
  397.                  MACHINE CODE             ASSEMBLER INSTRUCTION
  398.                     A1 0000 E               mov   ax, variable5 
  399.  
  400.              If variable5 is declared external in SEG1 or SEG3 or SEG4, the
  401.              assembler will write the appropriate segment override in the
  402.              code.
  403.  
  404.                     MACHINE CODE               ASSEMBLER INSTRUCTION
  405.                                  
  406.                     2E: A1 0000 E                mov   ax, variable5
  407.                     26: A1 0000 E                mov   ax, variable5 
  408.                     36: A1 0000 E                mov   ax, variable5 
  409.                                  
  410.              The "E" after the machine code means that the assembler knows
  411.              that the variable is external and it will tell the linker so the
  412.              linker can put the correct offset address at that point in the
  413.              machine code.
  414.  
  415.              Remember, as always, that it is your responsibility to have the
  416.              correct segment address in the segment register before using a
  417.              variable.
  418.  
  419.              Now we know where it goes. When you declare a variable external,
  420.              you must put the EXTRN statement in a segment which uses the same
  421.              segment register as the EXTRN variable is going to use. If the
  422.              EXTRN variable will use DS, then the segment where the EXTRN
  423.              statement is must use DS. If the variable uses ES, then the
  424.              segment the EXTRN statement is in must use ES. In other words,
  425.              the ASSUME statement for the segment the variable is in must
  426.              match EXACTLY the ASSUME statement you would write if the
  427.              variable were internal, not external.{2}  Normally, this is DS,
  428.              but in special circumstances you might want something else. Also,
  429.              if there is no segment that exactly matches what you want, then
  430.              you need to create a dummy segment:
  431.  
  432.                  DUMMY_SEG  SEGMENT
  433.                       EXTRN  variable7:QWORD
  434.                  DUMMY_SEG  ENDS
  435.  
  436.              and make the assume statement that you want:
  437.  
  438.              ____________________
  439.  
  440.                 2. This means that if the segment with the EXTRN statement has
  441.              more than one segment register in the assume statement:
  442.  
  443.                  ASSUME  ds:MORESTUFF, es:MORESTUFF
  444.  
  445.              then both those registers must be set to the segment of the
  446.              external variable when using it or your results may be
  447.              unreliable.
  448.  
  449.  
  450.  
  451.  
  452.              The PC Assembler Tutor                                        144
  453.              ______________________
  454.  
  455.                  ASSUME    es:DUMMY_SEG
  456.  
  457.  
  458.  
  459.              What segment has DS in an ASSUME statement? DATASTUFF in both
  460.              files, so that is where the EXTRN declaration goes - in the
  461.              DATASTUFF segment.
  462.  
  463.              ;prog1
  464.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  465.              PUBLIC sub1_message, sub3_message 
  466.              EXTRN  main_message:BYTE, sub2_message:BYTE 
  467.              sub1_message  db   "This is subroutine1.", 0 
  468.              sub3_message  db   "This is subroutine 3.", 0 
  469.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  470.  
  471.              ;prog2
  472.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  473.              PUBLIC main_message, sub2_message 
  474.              EXTRN  sub1_message:BYTE, sub3_message:BYTE 
  475.              main_message  db   "This is the entry routine.", 0 
  476.              sub2_message  db   "This is subroutine2.", 0 
  477.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  478.  
  479.              Change the data in the two files, assemble them again and link
  480.              them again:
  481.  
  482.                  link prog1+prog2+\asmhelp.obj
  483.  
  484.              You should get the same results as before. We are now through
  485.              with these programs. Make sure you understand how to define
  486.              PUBLIC and EXTRN procedures and PUBLIC and EXTRN data before
  487.              going on, since we are not going to cover it again. Everything
  488.              else in this chapter will be done with a single file in order to
  489.              make life easier. 
  490.  
  491.  
  492.              PASSING DATA
  493.  
  494.              When you pass data to the routines in ASMHELP.OBJ, you always
  495.              pass it through the AX register. The reason for this is that you
  496.              needed to use these routines before you knew much about 8086
  497.              assembler language. It is solely for the convenience of beginners
  498.              and is totally non-standard. In the real world, when you call a
  499.              subroutine you ALWAYS pass the data on the stack, no matter which
  500.              language you are using.
  501.  
  502.              If you have the C statement:
  503.  
  504.                  my_procedure (variable1, variable2, variable3) ;
  505.  
  506.              then the C compiler will generate the following code:
  507.  
  508.                  push variable3
  509.                  push variable2
  510.                  push variable1
  511.  
  512.  
  513.  
  514.  
  515.  
  516.              Chapter 15 - Subroutines                                      145
  517.              ________________________
  518.  
  519.                  call my_procedure{3}
  520.  
  521.              The C language pushes these variables in right to left order.
  522.              Before the call instruction is executed variable1 is on the top
  523.              of the stack, variable2 is the next down, and variable3 is third
  524.              on the stack. Is variable1 still on the stack top after the call
  525.              instruction is executed? No. The call instruction pushes either
  526.              one or two words on the stack. Before you go any farther with
  527.              subroutines you need to know how the call and return instruction
  528.              operate.
  529.  
  530.              Every time you have used show_regs, both CS the code segment
  531.              address and IP the instruction pointer have been displayed. What
  532.              does IP do? When the 8086 is ready to execute an instruction, it
  533.              takes IP, adds it to CS to calculate the total address, and gets
  534.              the instruction at that address. It then immediately figures out
  535.              how long the instruction is going to be and adds that amount to
  536.              IP.{4} What this means is that at any time, IP points to the NEXT
  537.              instruction, not the current instruction. When you execute a
  538.              call, the 8086 changes IP to point to the first byte of the
  539.              called subroutine, so the next instruction executed is the first
  540.              byte of the called subroutine.
  541.  
  542.              There are two different types of procedures, near procedures and
  543.              far procedures. In a near procedure, you keep CS, the code
  544.              segment register, the same. In a far procedure you change CS. So,
  545.              when you call a near procedure you change one thing (IP) and in a
  546.              far procedure you change two things (IP and CS).
  547.  
  548.              When you want to get back from the subroutine, you need to have
  549.              CS with the segment of the calling routine and IP with the
  550.              address of the instruction after the call. What are the mechanics
  551.              of all this? Let's take a near procedure first.
  552.  
  553.              In a near call, the 8086 first changes the instruction pointer to
  554.              point to the next instruction. It then pushes IP on the stack,
  555.              and puts the address of the called subroutine (which is in bytes
  556.              2 and 3 of the call instruction) in IP. IP now points to the
  557.              called subroutine. There is one more word (2 bytes) on the stack.
  558.              At the end of the called subroutine, a NEAR return (ret) pops the
  559.              top word off the stack into IP. IP then points to the instruction
  560.              after the call instruction. 
  561.  
  562.              In a far call, the 8086 first changes the instruction pointer
  563.              (IP) to point to the next instruction. It then pushes CS on the
  564.              stack, followed by IP. It then loads the offset address of the
  565.              called subroutine in IP and the segment address of the called
  566.              subroutine in CS. This new IP is in bytes 2 and 3 of the call
  567.              instruction and the new CS is in bytes 4 and 5 of the call
  568.              ____________________
  569.  
  570.                 3. You C fanatics will notice that there are some initial
  571.              underscores missing. Let's not confuse the issue.
  572.  
  573.                 4. Instructions can vary from one byte long to six bytes long,
  574.              and the 8086 can tell from the first (or first and second)
  575.              byte(s) how long the total instruction will be.
  576.  
  577.  
  578.  
  579.  
  580.              The PC Assembler Tutor                                        146
  581.              ______________________
  582.  
  583.              instruction. IP and CS now have the address of the called
  584.              subroutine. The stack has two words (4 bytes) more on the stack.
  585.              The old IP is the stack top and the old CS is next on the stack.
  586.              At the end of the subroutine, a FAR return (ret) pops the stack
  587.              top into IP, then pops the next stack item into CS. Now IP and CS
  588.              point to the instruction after the call instruction.
  589.  
  590.              These are two different types of call and they have two different
  591.              machine codes. These are two different types of returns and they
  592.              have two different machine codes.
  593.  
  594.  
  595.                  MACHINE CODE                  ASSEMBLER INSTRUCTIONS
  596.  
  597.                                                ; a far routine
  598.                                                ;----- 
  599.                                                far_routine proc far 
  600.                    CB                            ret 
  601.                                                far_routine endp 
  602.                                                ;-----
  603.  
  604.                                                ; a near routine
  605.                                                ;----- 
  606.                                                near_routine proc near 
  607.                    C3                            ret 
  608.                                                near_routine endp 
  609.                                                ;----- 
  610.  
  611.  
  612.                                                  ; a near and far call
  613.                     E8 0A43 R                    call near_routine 
  614.                     9A 015C ---- R               call far_routine 
  615.  
  616.  
  617.              The machine code for a near return is C3; for a far return it's
  618.              CB. The machine code for a near call is E8; for a far call it's
  619.              9A. The near call has the address of the called routine (0A43h)
  620.              in the following two bytes. The far call has the address of the
  621.              the called routine (015Ch) in the next two bytes followed by the
  622.              segment of the called routine. The segment address isn't there
  623.              yet. It will be put there by the linker and loader, but the
  624.              assembler has saved the space for the address. That's why the
  625.              dashes are there. Remember, the R is there because those
  626.              addresses might be relocated by the linker or the loader. 
  627.  
  628.              You tell the assembler whether to code a near return or far
  629.              return by telling it whether it is a near or a far procedure.
  630.  
  631.                  routine1  proc near
  632.                  routine2  proc far
  633.  
  634.              How does the assembler know whether to code a near or far call?
  635.              If it has already seen the procedure, it knows what type it is.
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.              Chapter 15 - Subroutines                                      147
  645.              ________________________
  646.  
  647.              If it hasn't seen it yet, it uses the default type.{5} If it is
  648.              an external subroutine, the assembler knows because you have
  649.              written an EXTRN statement.
  650.  
  651.                  EXTRN  routine3:NEAR, routine4:FAR
  652.  
  653.              This EXTRN statement should appear before the call.
  654.  
  655.              What if the routine appears after the call in the source file but
  656.              it isn't the default type? You can override the default type.
  657.  
  658.                  call NEAR PTR routine5
  659.                  call FAR PTR routine6
  660.  
  661.              This is the same cumbersome syntax that we had with pointers to
  662.              data, but it's the only game in town. Normally, if the subroutine
  663.              appears after the call, you don't need to do anything if it is a
  664.              near call but you need to put a FAR PTR override if it is a far
  665.              call. 
  666.  
  667.  
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.              ____________________
  700.  
  701.                 5. The default is near for what we are doing. However,
  702.              Microsoft has something called "simplified" directives and the
  703.              default changes in these cases.
  704.  
  705.