Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- Peter Norton Programmer's Guide - Norton Guide http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]

  A subroutine interface is a layer of assembly-language code that lets a
  program written in a high-level language communicate with an
  assembly-language subroutine. A subroutine interface has two main parts: a
  control interface and a data interface.

  The control interface handles the business of calling and returning; that
  is, of passing control of the computer from the calling program to a
  subroutine and back again. The control interface, by the way, can be
  tricky to program. It is remarkably simple if you know how to program
  properly, but you can create incredible messes if you make even minor
  programming errors.

  The data interface lets the calling program and a subroutine share data.
  In order to share successfully, you need to know how each side of the
  interface finds and works with data, and you must understand how data is
  formatted so that each side can interpret it in the same way. We'll be
  covering these topics in more detail in the next chapter.

  All three program elements--the calling program, the called subroutine,
  and the interface--must accomplish the following in order to work together
  successfully:

  The program must be able to find its way to the subroutine. In the
  8086-based system of the standard PC family, a subroutine is called
  through a CALL instruction. There are two kinds of CALL instruction:

  .  The near CALL locates a subroutine within the current 64 KB code
     segment (CS) and does not require the CS register to be changed.

  .  The far CALL locates a subroutine outside the current CS using a
     complete segmented address in the CALL instruction (which changes the
     CS setting). Because it needs to access only one executable code
     segment, a small-model or compact-model program uses near CALLs to call
     subroutines. A medium-model or large-model program uses far CALLs so
     that it can change CS and access multiple code segments.

  The subroutine must know what to do when finished. A subroutine typically
  returns to the calling program with an instruction that corresponds to the
  way it was called (that is, with a near or far RET instruction).
  Occasionally, however, a subroutine does something unusual--for example,
  you may want to terminate a program and return to DOS from a subroutine.

  The subroutine must know what supporting framework is provided by the
  caller. A typical supporting framework describes how the segment registers
  are set and whether a stack is available for use. In general, the segment
  registers are exactly as they should be: CS has the right code segment, DS
  points to the location of the calling program's data, and SS and SP are
  set up with the caller's stack.

  The called subroutine usually can continue to use the caller's stack, but
  there is no practical way to know how much working space is available. If
  the subroutine's needs are reasonable--say, fewer than 64 bytes--the
  caller's stack space should be adequate. However, if the subroutine should
  need more working space, it can set up its own stack space in memory.

  If the program needs to pass information (parameters) to the subroutine,
  both the program and the subroutine must know how many parameters exist,
  where they are, and what they are. Programs and subroutines typically work
  with a fixed number of parameters, although some languages, including C,
  can handle a variable number of parameters. The parameters are usually
  passed to the subroutine through the stack, either directly or indirectly.
  The direct method, known as pass-by-value, passes the actual value of the
  parameter through the stack; the indirect method, known as
  pass-by-reference, passes the parameter's address through the stack.

  The parameter-passing method used depends primarily on the language; some
  languages place only addresses--never parameter values--on the stack. With
  languages that can handle both addresses and values, you have a lot more
  freedom to decide which method to use, and the method you use lets you
  control how the parameters are dealt with as they are passed from one
  program to another.

  For example, if you want to protect a caller's parameter from being
  changed by the called subroutine, you'll use the pass-by-value method to
  pass a copy of the parameter's value on the stack. But if you want the
  parameter's value to be changed by the called subroutine, you must use the
  pass-by-reference method so that the subroutine can change the parameter's
  value by modifying the contents of memory at the specified address.

  Parameter passing is the most complicated part of the subroutine
  interface, made even more complicated by the different ways programming
  languages deal with data and stack information. Because of its complexity
  and variability from one language to another, parameter passing is the
  main issue we'll discuss in our language comparisons in the next chapter.

  The subroutine must preserve certain information. Although requirements
  may vary in different situations, a few ground rules govern what
  information should be preserved, and what can and cannot be done when
  calling a subroutine.

  .  Interrupts can be suspended briefly when segment registers are changed;
     they must be turned back on before returning. (See page 52.)

  .  The contents of any CPU registers used by the calling program as well
     as the subroutine are preserved by being pushed on the stack.

  .  The BP and DS registers should usually be saved and restored if they
     are changed within a subroutine.

  Register usage varies: One compiler may rely on the contents of ES being
  constant, and another might require you to preserve SI and DI if you use
  them in a subroutine. See your compiler manual for specific information.

  The stack must be cleaned up after the subroutine is finished. Four things
  might clutter the stack when a subroutine is finished: some parameters,
  the return address from the CALL instruction, register values saved from
  before the CALL, and some working storage from the subroutine.

  Three of these leftovers are not problems: Subroutines are expected to
  remove their own working storage from the stack, saved registers are
  removed by POP instructions, and the return address is removed by the RET
  instruction. The parameters, however, usually complicate the clean-up
  process, because the method of removal varies in different languages. Some
  languages expect the subroutine to remove the parameters by specifying in
  the RET instruction the number of bytes to remove from the stack. Other
  languages expect the caller to remove them. We'll point out these
  differences as we discuss some languages in detail in Chapter 20.

  With all these program design elements in mind, let's step back a bit
  farther and see how the whole process works--from creating a program or
  subroutine to combining it with others.

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson