home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / disks / disk437.lzh / Flip / small.txt < prev   
Text File  |  1991-01-16  |  9KB  |  161 lines

  1.  
  2.                      Maintaining The Small Data Model
  3.                            with C and Assembler
  4.  
  5.                      ================================
  6.  
  7.                            by Michael J. Monaco
  8.  
  9.  
  10. First of all, what is a data model?  As discussed in this article, a data
  11. model represents a method for addressing data storage elements within the
  12. scope of a single program at the machine code level.  Or, to put it another
  13. way, it is the method by which the executable machine code will address the
  14. data stored in defined data section of the program.  Why is this important?
  15. Depending on the data model chosen, the size or speed of a program will be
  16. affected.  It is important to note that not all data storage used in a
  17. program is subject to this model.  Generally, the data model is applied to
  18. globally defined data storage.  It is not applied to dynamically allocated
  19. memory, stack storage, or the cpu registers since these locations will
  20. automaticallybe addressed in the most efficient method possible.
  21.  
  22. There are two types of data models to chose from, Large and Small.  In the
  23. large data model, the location of a defined data element will be encoded in
  24. the operand field of an instruction as a full 32 bit address. This address is
  25. immediately usable without modification. The advantage is no practical limit
  26. to the size of a programs data space.  The disadvantage is a larger program
  27. and a slower program on the 68000 microprocessor. Larger because a machine
  28. instruction with operands using the large data model can be from 6 to 10
  29. bytes long. That's 2 bytes for the operation and 4 to 8 bytes for addressing.
  30. (Fig 1a) Slower because of the two memory accesses required to fetch the full
  31. 32 bit address over a 16 bit wide data path. It also takes longer to load a
  32. program with large data since the addresses are relocatable (not known till
  33. execution time) and must be adjusted.
  34.  
  35. The small data model reverses the benefits/disadvantages of the large data
  36. model. In the small data model, the location of a data element is encoded as
  37. the contents of an address register plus a 16 bit offset given in the
  38. operand. The address register is chosen by the assembler and it is loaded
  39. with a calculated value at the beginning of program execution. Lets call it
  40. the base register. The 16 bit offset has an effective range of 64K bytes and
  41. is used such that the address generated is plus or minus 32K from the
  42. location loaded in the address register. And only one base register is
  43. provided and can not be changed during execution. This leads to a limited
  44. data address space of 64K for predefined data. On the other hand the code
  45. size of the program is small and it will execute faster.  A complete
  46. instruction will be only 4 to 6 bytes long and will require only one memory
  47. access to fetch the offset.  (Fig 1b) Since the offsets are based on a
  48. register to be loaded at run time, there are no addresses that require
  49. adjusting and the program will load faster.
  50.  
  51. So what's the big deal? Just use the Large model for large programs and the
  52. Small model for small programs.  Normally that's the way its done, but
  53. interrupt handlers require special consideration.  They are usually small in
  54. size but by the nature of the way they are executed, using the Small data
  55. model creates a problem.  The Large data model can be used at the expense of
  56. size and speed, but that would be to easy.  In the accompanying article we
  57. saw how interrupt handlers can be installed and how they can signal the
  58. process into action.  Installing the handler really only consisted of adding
  59. an initialized interrupt structure, with a pointer to the handler, into the
  60. appropriate interrupt list.  When the interrupt gets executed, all the system
  61. does is load the arguments to be passed in the appropriate registers and
  62. calls the subroutine at the address specified in the interrupt structure.
  63. The state of the registers at the time the interrupt is executed will not be
  64. same as when the handler was installed.  Therefore, the handler cannot depend
  65. on using the base address register for referencing data.  Any attempt to do
  66. so will usually end up with a visit from the GURU.
  67.  
  68. Now the big question.  How can we use the Small data model and reference
  69. globally defined data from within the interrupt handler?  Use another
  70. addressing mode that allows the use of a register plus displacement such that
  71. the value in the register will be guaranteed.  In particular, the addressing
  72. mode called "Program Counter with Displacement".  The program counter is
  73. guaranteed to contain the address of the next instruction to be executed, and
  74. a 16 bit offset can be specified to reference data based on this fact.
  75. Because of the way data and code are processed by the assembler, the data
  76. referenced with PC addressing must be within the code segment of the program.
  77. This means that the data that was globally defined must be moved to within
  78. the code segment.  (Based on the Manx 3.6a assembler)
  79.  
  80. Lets look at some code from Flip v2.0 to illustrate the method.
  81.  
  82.     ULONG window_signal; /* global storage of an allocated window signal */
  83.  
  84. The above declaration will allocate 4 bytes of storage that will be visible
  85. to all parts of the program. The C part of the program will store an
  86. allocated signal here for use by the input handler.  Normally an assembler
  87. code segment could reference this data item also, but its method of access
  88. would be assembled with the same data model as the C code.
  89.  
  90.     window_signal = 1L << window_signal_bit;
  91.  
  92. Here we are storing some data.  The reference to window_signal at this point
  93. will use the small data model. It will look something like this after compile
  94. and assembly:
  95.  
  96.     move.l    d0,window_signal_offset_from(a4)
  97.  
  98. where a4 is the base address register.  Now that the data is stored, it is
  99. still not accessible by the input handler.  To attempt to access
  100. window_signal from the handler with the small data model would cause the
  101. system to crash. This is because the register a4 is not valid at the time the
  102. handler is called.  So what we have to do is move it someplace that can be
  103. safely accessed.
  104.  
  105.     ;   /* it is good practice to start and end inline assembler code */
  106.         /* with dummy C statements */
  107.     #asm
  108.       lea       _ws_,a0                 ; get the address of where we are
  109.                                         ; moving window_signal to.
  110.       move.l    _window_signal,(a0)     ; and move it.
  111.     #endasm
  112.     ;
  113.  
  114. With the Manx assembler we can't just say "move window_signal to _ws_"
  115. because _ws_ is in the code segment of the program. Instead we get the
  116. address of _ws_ and move it by indirect reference.  Notice that this move
  117. statement does reference window_signal and the assembler will change it to
  118. use the small data model.  It is ok at this point because we are in the
  119. installation stage of the program and not in the handler code section.
  120. Register a4 will be valid. Now where is _ws_?  Its in the code segment near
  121. the handler routine between the functions.
  122.  
  123.     #asm
  124.               cseg                ; storage must be accessible but not
  125.               ds.l    0           ; restricted by the small data model.
  126.       _ws_    dc.l    0           ; copy of window signal from startup
  127.  
  128.     #endasm
  129.  
  130. The above declaration will first align on a longword boundary and then
  131. allocate 4 bytes of space.  Why don't we just move the window signal to _ws_
  132. with the C code?  Its not possible with out some special manipulation of the
  133. assembler source between the compile and assembler stages.  This is because
  134. the 68000 instruction set does not support PC addressing as the destination
  135. address.  OK, so now we have the data stored in the code section of the
  136. program and now the input handler can access it using PC addressing.
  137.  
  138.     #asm
  139.        move.l   _ws_(pc),d0       ; yes - user wants to flip windows
  140.     #endasm
  141.  
  142. Yep, That's it.  Not quite what you expected?  Well, the important thing to
  143. notice with this addressing mode is (1) the value in the program counter will
  144. be the address of the next instruction to be executed and (2) the offset _ws_
  145. is the number of bytes from the next instruction to the storage area "_ws_".
  146. It is independent of the state of any address registers and therefore safe to
  147. use in an interrupt handler.
  148.  
  149. You might be wondering why _ws_ had to be in the code segment.  Notice that
  150. addressing with a base register (as with the small data model) and addressing
  151. with the PC both use an offset.  The instructions themselves are basically of
  152. the same type, "Address Register Indirect with Displacement", the distinction
  153. is when the offset is calculated.  With PC addressing the offset is
  154. calculated at assembly time.  The assembler sees _ws_ and knows the distance
  155. between it and the next instruction. With a base register and the small data
  156. model, data can be located in any module and the offset cannot be calculated
  157. until link time when all the data is pooled into one data segment.
  158.  
  159.  
  160. Happy Programming.
  161.