377 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			377 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| .BP
 | |
| .SN 4
 | |
| .S1 "DATA ADDRESS SPACE"
 | |
| The data address space is divided into three parts, called 'areas',
 | |
| each with its own addressing method:
 | |
| global data area,
 | |
| local data area (including the stack),
 | |
| and heap data area.
 | |
| These data areas must be part of the same
 | |
| address space because all data is accessed by
 | |
| the same type of pointers.
 | |
| .P
 | |
| Space for global data is reserved using several pseudoinstructions in the
 | |
| assembly language, as described in
 | |
| the next paragraph and chapter 11.
 | |
| The size of the global data area is fixed per program.
 | |
| .A
 | |
| Global data is addressed absolutely in the machine language.
 | |
| Many instructions are available to address global data.
 | |
| They all have an absolute address as argument.
 | |
| Examples are LOE, LAE and STE.
 | |
| .P
 | |
| Part of the global data area is initialized by the
 | |
| compiler, the
 | |
| rest is not initialized at all or is initialized
 | |
| with a value, typically -32768 or 0.
 | |
| Part of the initialized global data may be made read-only
 | |
| if the implementation supports protection.
 | |
| .P
 | |
| The local data area is used as a stack,
 | |
| which grows from high to low addresses
 | |
| and contains some data for each active procedure
 | |
| invocation, called a 'frame'.
 | |
| The size of the local data area varies dynamically during
 | |
| execution.
 | |
| Below the current procedure frame resides the operand stack.
 | |
| The stack pointer SP always points to the bottom of
 | |
| the local data area.
 | |
| Local data is addressed by offsetting from the local base pointer LB.
 | |
| LB always points to the frame of the current procedure.
 | |
| Only the words of the current frame and the parameters
 | |
| can be addressed directly.
 | |
| Variables in other active procedures are addressed by following
 | |
| the chain of statically enclosing procedures using the LXL or LXA instruction.
 | |
| The variables in dynamically enclosing procedures can be
 | |
| addressed with the use of the DCH instruction.
 | |
| .A
 | |
| Many instructions have offsets to LB as argument,
 | |
| for instance LOL, LAL and STL.
 | |
| The arguments of these instructions range from -1 to some
 | |
| (negative) minimum
 | |
| for the access of local storage and from 0 to some (positive)
 | |
| maximum for parameter access.
 | |
| .P
 | |
| The procedure call instructions CAL and CAI each create a new frame
 | |
| on the stack.
 | |
| Each procedure has an assembly-time parameter specifying
 | |
| the number of bytes needed for local storage.
 | |
| This storage is allocated each time the procedure is called and
 | |
| must be a multiple of the wordsize.
 | |
| Each procedure, therefore, starts with a stack with the local variables
 | |
| already allocated.
 | |
| The return instructions RET and RTT remove a frame.
 | |
| The actual parameters must be removed by the calling procedure.
 | |
| .P
 | |
| RET may copy some words from the stack of
 | |
| the returning procedure to an unnamed 'function return area'.
 | |
| This area is available for 'READ-ONCE' access using the LFR instruction.
 | |
| The result of a LFR is only defined if the size used to fetch
 | |
| is identical to the size used in the last return.
 | |
| The instruction ASP, used to remove the parameters from the
 | |
| stack, the branch instruction BRA and the non-local goto
 | |
| instrucion GTO are the only ones that leave the contents of
 | |
| the 'function return area' intact.
 | |
| All other instructions are allowed to destroy the function
 | |
| return area.
 | |
| Thus parameters can be popped before fetching the function result.
 | |
| The maximum size of all function return areas is
 | |
| implementation dependent,
 | |
| but should allow procedure instance identifiers and all
 | |
| implemented objects of type integer, unsigned, float
 | |
| and pointer to be returned.
 | |
| In most implementations
 | |
| the maximum size of the function return
 | |
| area is twice the pointer size,
 | |
| because we want to be able to handle 'procedure instance
 | |
| identifiers' which consist of a procedure identifier and the LB
 | |
| of a frame belonging to that procedure.
 | |
| .P
 | |
| The heap data area grows upwards, to higher numbered
 | |
| addresses.
 | |
| It is initially empty.
 | |
| The initial value of the heap pointer HP
 | |
| marks the low end.
 | |
| The heap pointer may be manipulated
 | |
| by the LOR and STR instructions.
 | |
| The heap can only be addressed indirectly,
 | |
| by pointers derived from previous values of HP.
 | |
| .S2 "Global data area"
 | |
| The initial size of the global data area is determined at assembly time.
 | |
| Global data is allocated by several
 | |
| pseudoinstructions in the EM assembly
 | |
| language.
 | |
| Each pseudoinstruction allocates one or more bytes.
 | |
| The bytes allocated for a single pseudo form
 | |
| a 'block'.
 | |
| A block differs from a fragment, because,
 | |
| under certain conditions, several blocks are allocated
 | |
| in a single fragment.
 | |
| This guarantees that the bytes of these blocks
 | |
| are consecutive.
 | |
| .P
 | |
| Global data is addressed absolutely in binary
 | |
| machine language.
 | |
| Most compilers, however,
 | |
| cannot assign absolute addresses to their global variables,
 | |
| especially not if the language
 | |
| allows programs to be composed of several separately compiled modules.
 | |
| The assembly language therefore allows the compiler to name
 | |
| the first address of a global data block with an alphanumeric label.
 | |
| Moreover, the only way to address such a named global data block
 | |
| in the assembly language is by using its name.
 | |
| It is the task of the assembler/loader to
 | |
| translate these labels into absolute addresses.
 | |
| These labels may also be used
 | |
| in CON and ROM pseudoinstructions to initialize pointers.
 | |
| .P
 | |
| The pseudoinstruction CON allocates initialized data.
 | |
| ROM acts like CON but indicates that the initialized data will
 | |
| not change during execution of the program.
 | |
| The pseudoinstruction BSS allocates a block of uninitialized
 | |
| or identically initialized
 | |
| data.
 | |
| The pseudoinstruction HOL is similar to BSS,
 | |
| but it alters the meaning of subsequent absolute addressing in
 | |
| the assembly language.
 | |
| .P
 | |
| Another type of global data is a small block,
 | |
| called the ABS block, with an implementation defined size.
 | |
| Storage in this type of block can only be addressed
 | |
| absolutely in assembly language.
 | |
| The first word has address 0 and is used to maintain the
 | |
| source line number.
 | |
| Special instructions LIN and LNI are provided to
 | |
| update this counter.
 | |
| A pointer at location 4 points to a string containing the
 | |
| current source file name.
 | |
| The instruction FIL can be used to update the pointer.
 | |
| .P
 | |
| All numeric arguments of the instructions that address
 | |
| the global data area refer to locations in the
 | |
| ABS block unless
 | |
| they are preceded by at least one HOL pseudo in the same
 | |
| module,
 | |
| in which case they refer to the storage area allocated by the
 | |
| last HOL pseudoinstruction.
 | |
| Thus LOE 0 loads the zeroth word of the most recent HOL, unless no HOL has
 | |
| appeared in the current file so
 | |
| far, in which case it loads the zeroth word of the
 | |
| ABS fragment.
 | |
| .P
 | |
| The global data area is highly fragmented.
 | |
| The ABS block and each HOL and BSS block are separate fragments.
 | |
| The way fragments are formed from CON and ROM blocks is more complex.
 | |
| The assemblers group several blocks into a single fragment.
 | |
| A fragment only contains blocks of the same type: CON or ROM.
 | |
| It is guaranteed that the bytes allocated for two consecutive CON pseudos are
 | |
| allocated consecutively in a single fragment, unless
 | |
| these CON pseudos are separated in the assembly language program
 | |
| by a data label definition or one or more of the following pseudos:
 | |
| .DS
 | |
| 
 | |
|      ROM, BSS, HOL and END
 | |
| 
 | |
| .DE
 | |
| An analogous rule holds for ROM pseudos.
 | |
| .S2 "Local data area"
 | |
| The local data area consists of a sequence of frames, one for
 | |
| each active procedure.
 | |
| Below the frame of the current procedure resides the
 | |
| expression stack.
 | |
| Frames are generated by procedure calls and are
 | |
| removed by procedure returns.
 | |
| A procedure frame consists of six 'zones':
 | |
| .DS
 | |
| 
 | |
|   1.  The return status block
 | |
|   2.  The local variables and compiler temporaries
 | |
|   3.  The register save block
 | |
|   4.  The dynamic local generators
 | |
|   5.  The operand stack.
 | |
|   6.  The parameters of a procedure one level deeper
 | |
| 
 | |
| .DE
 | |
| A sample frame is shown in Figure 1.
 | |
| .P
 | |
| Before a procedure call is performed the actual
 | |
| parameters are pushed onto the stack of the calling procedure.
 | |
| The exact details are compiler dependent.
 | |
| EM allows procedures to be called with a variable number of
 | |
| parameters.
 | |
| The implementation of the C-language almost forces its runtime
 | |
| system to push the parameters in reverse order, that is,
 | |
| the first positional parameter last.
 | |
| Most compilers use the C calling convention to be compatible.
 | |
| The parameters of a procedure belong to the frame of the
 | |
| calling procedure.
 | |
| Note that the evaluation of the actual parameters may imply
 | |
| the calling of procedures.
 | |
| The parameters can be accessed with certain instructions using
 | |
| offsets of 0 and greater.
 | |
| The first byte of the last parameter pushed has offset 0.
 | |
| Note that the parameter at offset 0 has a special use in the
 | |
| instructions following the static chain (LXL and LXA).
 | |
| These instructions assume that this parameter contains the LB of
 | |
| the statically enclosing procedure.
 | |
| Procedures that do not have a dynamically enclosing procedure
 | |
| do not need a static link at offset 0.
 | |
| .P
 | |
| Two instructions are available to perform procedure calls, CAL
 | |
| and CAI.
 | |
| Several tasks are performed by these call instructions.
 | |
| .A
 | |
| First, a part of the status of the calling procedure is
 | |
| saved on the stack in the return status block.
 | |
| This block should contain the return address of the calling
 | |
| procedure, its LB and other implementation dependent data.
 | |
| The size of this block is fixed for any given implementation
 | |
| because the lexical instructions LPB, LXL and LXA must be able to
 | |
| obtain the base addresses of the procedure parameters \fBand\fP local
 | |
| variables.
 | |
| An alternative solution can be used on machines with a highly
 | |
| segmented address space.
 | |
| The stack frames need not be contiguous then and the first
 | |
| status save area can contain the parameter base AB,
 | |
| which has the value of SP just after the last parameter has
 | |
| been pushed.
 | |
| .A
 | |
| Second, the LB is changed to point to the
 | |
| first word above the local variables.
 | |
| The new LB is a copy of the SP after the return status
 | |
| block has been pushed.
 | |
| .A
 | |
| Third, the amount of local storage needed by the procedure is
 | |
| reserved.
 | |
| The parameters and local storage are accessed by the same instructions.
 | |
| Negative offsets are used for access to local variables.
 | |
| The highest byte, that is the byte nearest
 | |
| to LB, has to be accessed with offset -1.
 | |
| The pseudoinstruction specifying the entry point of a
 | |
| procedure, has an argument that specifies the amount of local
 | |
| storage needed.
 | |
| The local variables allocated by the CAI or CAL instructions
 | |
| are the only ones that can be accessed with a fixed negative offset.
 | |
| The initial value of the allocated words is
 | |
| not defined, but implementations that check for undefined
 | |
| values will probably initialize them with a
 | |
| special 'undefined' pattern, typically -32768.
 | |
| .A
 | |
| Fourth, any EM implementation is allowed to reserve a variable size
 | |
| block beneath the local variables.
 | |
| This block could, for example, be used to save a variable number
 | |
| of registers.
 | |
| .A
 | |
| Finally, the address of the entry point of the called procedure
 | |
| is loaded into the Program Counter.
 | |
| .P
 | |
| The ASP instruction can be used to allocate further (dynamic)
 | |
| local storage.
 | |
| The base address of such storage must be obtained with a LOR~SP
 | |
| instruction.
 | |
| This same instruction ASP may also be used
 | |
| to remove some words from the stack.
 | |
| .P
 | |
| There is a version of ASP, called ASS, which fetches the number
 | |
| of bytes to allocate from the stack.
 | |
| It can be used to allocate space for local
 | |
| objects whose size is unknown at compile time,
 | |
| so called 'dynamic local generators'.
 | |
| .P
 | |
| Control is returned to the calling procedure with a RET instruction.
 | |
| Any return value is then copied to the 'function return area'.
 | |
| The frame created by the call is deallocated and the status of
 | |
| the calling procedure is restored.
 | |
| The value of SP just after the return value has been popped must
 | |
| be the same as the
 | |
| value of SP just before executing the first instruction of this
 | |
| invocation.
 | |
| This means that when a RET is executed the operand stack can
 | |
| only contain the return value and all dynamically generated locals must be
 | |
| deallocated.
 | |
| Violating this restriction might result in hard to detect
 | |
| errors.
 | |
| The calling procedure has to remove the parameters from the stack.
 | |
| This can be done with the aforementioned ASP instruction.
 | |
| .P
 | |
| Each procedure frame is a separate fragment.
 | |
| Because any fragment may be placed anywhere in memory,
 | |
| procedure frames need not be contiguous.
 | |
| .DS
 | |
|                 |===============================|
 | |
|                 |     actual parameter  n-1     |
 | |
|                 |-------------------------------|
 | |
|                 |              .                |
 | |
|                 |              .                |
 | |
|                 |              .                |
 | |
|                 |-------------------------------|
 | |
|                 |     actual parameter  0       | ( <- AB )
 | |
|                 |===============================|
 | |
| 
 | |
| 
 | |
|                 |===============================|
 | |
|                 |///////////////////////////////|
 | |
|                 |///// return status block /////|
 | |
|                 |///////////////////////////////|   <- LB
 | |
|                 |===============================|
 | |
|                 |                               |
 | |
|                 |       local variables         |
 | |
|                 |                               |
 | |
|                 |-------------------------------|
 | |
|                 |                               |
 | |
|                 |      compiler temporaries     |
 | |
|                 |                               |
 | |
|                 |===============================|
 | |
|                 |///////////////////////////////|
 | |
|                 |///// register save block /////|
 | |
|                 |///////////////////////////////|
 | |
|                 |===============================|
 | |
|                 |                               |
 | |
|                 |   dynamic local generators    |
 | |
|                 |                               |
 | |
|                 |===============================|
 | |
|                 |           operand             |
 | |
|                 |-------------------------------|
 | |
|                 |           operand             |
 | |
|                 |===============================|
 | |
|                 |         parameter  m-1        |
 | |
|                 |-------------------------------|
 | |
|                 |              .                |
 | |
|                 |              .                |
 | |
|                 |              .                |
 | |
|                 |-------------------------------|
 | |
|                 |         parameter  0          | <- SP
 | |
|                 |===============================|
 | |
| 
 | |
|           Figure 1. A sample procedure frame and parameters.
 | |
| .DE
 | |
| .S2 "Heap data area"
 | |
| The heap area starts empty, with HP
 | |
| pointing to the low end of it.
 | |
| HP always contains a word address.
 | |
| A copy of HP can always be obtained with the LOR instruction.
 | |
| A new value may be stored in the heap pointer using the STR instruction.
 | |
| If the new value is greater than the old one,
 | |
| then the heap grows.
 | |
| If it is smaller, then the heap shrinks.
 | |
| HP may never point below its original value.
 | |
| All words between the current HP and the original HP
 | |
| are allocated to the heap.
 | |
| The heap may not grow into a part of memory that is already allocated
 | |
| for the stack.
 | |
| When this is attempted, the STR instruction will cause a trap to occur.
 | |
| .P
 | |
| The only way to address the heap is indirectly.
 | |
| Whenever an object is allocated by increasing HP,
 | |
| then the old HP value must be saved and can be used later to address
 | |
| the allocated object.
 | |
| If, in the meantime, HP is decreased so that the object
 | |
| is no longer part of the heap, then an attempt to access
 | |
| the object is not allowed.
 | |
| Furthermore, if the heap pointer is increased again to above
 | |
| the object address, then access to the old object gives undefined results.
 | |
| .P
 | |
| The heap is a single fragment.
 | |
| All bytes have consecutive addresses.
 | |
| No limits are imposed on the size of the heap as long as it fits
 | |
| in the available data address space.
 |