                   Chapter 14 - Machine Dependent Facilities


                      PREREQUISITES FOR THIS MATERIAL

             Before  attempting  to understand  this  material,  you
        should  understand the material presented in Part I of  this
        tutorial  and  a  clear  understanding of  the  material  on
        pointers in Part II.

                   THIS IS WHERE YOU CAN GET INTO TROUBLE

             Modula-2  does  a good job of insulating you  from  the
        underlying  peculiarities of your computer due to the strong
        TYPE checking which it does.  It can prevent you from making
        many  kinds of rather stupid blunders simply by forcing  you
        to  follow  its predefined conventions.   There  are  times,
        however,  when  you wish to ignore some of its help  and  do
        something that is out of the ordinary.  If you had a need to
        directly interface with some external device, you would need
        to  get down to the nitty gritty of the operating system and
        do  some  things  that are outside of the  realm  of  normal
        programming  practice.   Modula-2 will allow you to do  such
        things but you will pay a price because you take the  chance
        of hopelessly confusing the system.

             The  principles  taught in this chapter  can  lead  you
        directly  into the operating system where you will have more
        freedom than you would have thought possible with  Modula-2,
        but it will place more responsibility on you.  This material
        is  only for the advanced programmer because it will require
        a  knowledge of the inner workings of the computer  and  the
        operating system.   Nevertheless,  it would be good for you,
        as  a student of Modula-2,  to at least read this  material,
        examine the example programs, and compile and run them.  You
        will  then have a store of knowledge of these things so that
        you can use them when you need them.

                          TYPE RELAXATION EXAMPLE

             Load  and display the program named TYPEREL.MOD for  an
        example  of a program with some very unusual  type  transfer
        functions.   Note  first that three TYPES are defined,  each
        being  the same size considering storage requirements.   The
        first TYPE is 10 INTEGERS,  the second is 10 CARDINALS,  and
        the  third  is  20 CHAR variables which  requires  the  same
        amount  of storage as 10 INTEGERS or  CARDINALS.   The  fact
        that all three TYPES are the same size is very important for
        what we will do later in the program.

             The first thing we do in the program part of the MODULE
        is to assign a number to "Count",  a CARDINAL type variable.
        In  the next line we assign the value of "Count" to  "Index"
        even though they are of different TYPES because we transform


                                   Page 89









                   Chapter 14 - Machine Dependent Facilities


        the  TYPE in the same manner that we did back in  Chapter  3
        when  we studied TRANSFER.MOD but this time we will go a bit
        farther with the transformations.   Actually,  we don't need
        the  type  transformation here because INTEGER and  CARDINAL
        are assignment compatible.

             We  load  up  the  INTEGER array  "IntVars"  with  some
        nonsense  data to work with,  the data being the  series  of
        numbers  from  65 to 74,  which should be easy  for  you  to
        ascertain.   Then in line 23,  we copy one of the array data
        points  to  one  of the other to illustrate  that  the  type
        transformation works even on array elements.

                    NOW FOR THE BIG TYPE TRANSFORMATION

             In  line 24 of the program we copy the entire field  of
        10 INTEGER type variables into the array of 10 CARDINAL type
        variables.   The only restriction is that both of the fields
        must be exactly the same size which these two are.  In order
        to  do the transformation,  the TYPE of the  resulting  data
        area  is  used  in front of the parentheses  of  the  source
        variables.   Line  25 goes a step farther and copies the new
        CARDINAL  data  into  20  CHAR  type  variables,   which  is
        permissible  because 20 CHAR variables uses the same  amount
        of  storage  as  10  CARDINAL  variables.   You  could  even
        transform  a record made up of several different types  into
        all  CHAR  variables,  or  all  INTEGERS,  or  even  another
        completely different record.   The only requirement is  that
        both of the groups be exactly the same size.

             This may appear to be a really neat thing to be able to
        do  but there are problems that you will find with this  new
        transformation.   There  are no data conversions done,  only
        type  conversions,  which means that you may wind up with  a
        real mess trying to decipher just what the transformed  data
        means.   In  addition,  since  each compiler may define  the
        various types of data slightly different,  your program will
        not  be easily transportable to another computer,  or  maybe
        not even to another compiler on the same computer.

             Five  of  the  CARDINAL numbers are  displayed  on  the
        monitor,  then 10 of the CHAR numbers are displayed to  show
        you that they really are the same numbers.  The order of the
        numbers are reversed when output as individual bytes because
        of  the way the data is stored in the microprocessor in your
        computer.   This in itself is an indication that there is no
        data conversion, but only a data copying, byte by byte.

             One  other  rule must be pointed out,  you cannot do  a
        data transformation within a function call, but it is simple
        enough to do the transformation to a dummy variable and  use


                                   Page 90









                   Chapter 14 - Machine Dependent Facilities


        the   dummy  variable  in  the  function  call  if  that  is
        necessary.   This will be illustrated shortly.   Compile and
        run this program after you study it.

                         WORD AND ADDRESS VARIABLES

             Load and display WORDADDR.MOD for an example using some
        new data types.  In order to get down to the lowest level of
        the  machine,  we  need these  new  types,  ADR,  WORD,  and
        ADDRESS,  which  must  be  IMPORTED from the  pseudo  module
        SYSTEM.   The  pseudo  module SYSTEM does not  exist  as  an
        external module as the others do because the kinds of things
        it  does  are closely associated with the  compiler  itself.
        The designers of Modula-2 have therefore defined this module
        to make these things available to us.

             The  new data type "WORD" is compatible with  all  data
        types that use a single word for storage, but it is somewhat
        limited in what you can do with it. It is most useful as the
        formal  argument to a function which can be called with  any
        data  type that is contained in one word.   In lines 27  and
        28,  the same procedure is called, once with an INTEGER, and
        once  with a CARDINAL.   Since the procedure is designed  to
        handle either,  it will print out both numbers by converting
        them first to CARDINAL using the type transformation in line
        17,  then calling the output procedures.   Once  again,  the
        type  transformation cannot be done in the procedure call so
        a temporary variable is used.

                           A NEW KIND OF POINTER

             The variable "Peach" is assigned the type ADDRESS which
        is  also  imported from the pseudo  module  SYSTEM,  and  is
        therefore a pointer to any WORD type of variable.  Peach can
        therefore  point  to an INTEGER or a CARDINAL as is done  in
        lines 25 and 26.  The procedure "ADR" returns the address of
        any  WORD type of variable and it too must be IMPORTED  from
        the pseudo module SYSTEM.

                             ABSOLUTE ADDRESSES

             Notice  the  two strange looking variables in lines  10
        and 11.   The variable "MonoVideo" is an array of 4000  CHAR
        type variables but we have forced it to be located at a very
        specific location in memory, namely at segment=B000(hex) and
        offset=0000(hex).   This  is the method provided for you  by
        Modula-2  by  which  you  can force a variable to  be  at  a
        specific memory location.   In this case we have defined the
        variable  to be stored in the locations in memory where  the
        monochrome  monitor display is stored so we can  store  data
        directly into the monochrome monitor display area.


                                   Page 91









                   Chapter 14 - Machine Dependent Facilities



             The  variable "ColorVideo" is the same except that  the
        location  referenced  is  that area where the output  for  a
        color  monitor  is stored.   You can see that you  can  gain
        control over the actual hardware with this capability but it
        does  require  a lot of knowledge of the  hardware  and  the
        operating system.

             In the last line of the program the variable "Peach" is
        assigned   the   address  of  a  specific  location  as   an
        illustration only.  This is only possible because "Peach" is
        a variable of type ADDRESS.

             It should be clear to you that with these functions, it
        is  possible  to do a lot of data shuffling that  could  not
        otherwise be done.  The next example program will illustrate
        their use further.

                          MORE ADDRESSING EXAMPLES

             Load  and  display  the  program  ADRSTUFF.MOD.    This
        program  uses  the ADDRESS type and  adds  two  new,  rather
        simple functions,  SIZE and TSIZE.   Actually, these are not
        completly  new  since  we used the  TSIZE  function  in  the
        chapter  on  pointers  and dynamic  allocation.   These  two
        functions  will return the size in bytes of any variable  or
        of any type.   The program on your monitor has several types
        defined, then several variables, and finally initializes all
        of the elements of the array "Stuff" to some nonsense  data.
        The really interesting things begin happening at line 25.

             The pointer "NeatPoint" is pointed at the first element
        of  the  array "Stuff",  and its value is dereferenced  into
        "Index".   The  type transformation is required because  the
        result  of  the dereferencing is a CARDINAL.   The  data  is
        written  out.   Next  the  size of the  type  "IntArray"  is
        assigned to the variable "IncreAmt", which should be 8 words
        or  16 bytes.   In line 29 we do some pointer arithmetic  by
        adding the size of the type "IntArray" to the original value
        of  the pointer which should cause it to point to  the  next
        row  of  the  array.   After dereferencing the  pointer  and
        getting its new value,  we print it out to find that it  did
        indeed move to the next row of the array.

             Based on the above discussion, it should be apparent to
        you that you can move the pointer all around the array named
        "Stuff"  and get whatever data you wish.   The next  section
        uses  a loop to continue the process through all five  rows.
        The only thing that may be confusing is line number 34 where
        we get the size of the "BigArray" type and divide it by  the
        size  of the "IntArray" type.   The result should be 5,  and


                                   Page 92









                   Chapter 14 - Machine Dependent Facilities


        you will see that it does five iterations through the  loop.
        This  is  really a dumb way to get through  this  particular
        loop  but it is only for purposes of illustration that it is
        done.   Notice all of the type transformations to INTEGER in
        these statements, this is because the functions all return a
        CARDINAL  type  of  data.   Doing all of  this  in  CARDINAL
        numbers would have made it much cleaner,  but this was  more
        illustrative for you.

                       TWO MORE LINES OF ILLUSTRATION

             Lines 42 and 43 are given as an illustration for you of
        how to use the SIZE function.  It simply returns the size in
        bytes, of any variable used as an argument.

        PROGRAMMING EXERCISES

        1.   Modify  the "AdrStuff" module to print out some of  the
             type  and  variable sizes such as those  calculated  in
             lines 41 and 42.

        2.   Write a program with an array of 100 CARDINAL elements,
             fill the elements with nonsense data, and use a pointer
             to  print out every 12th value starting at the  highest
             element (number 100) and working downward.




























                                   Page 93
