The Format 1 instruction is also PC-relative.
So stored by shifting right 2 bits. Address after the call is :
npc = (instruction<29:0> << 2) + pc.
But the problem is that programs are frequently moved around in memory, and hence the calling addresses and the called addresses keep changing. The relative address remains fixed, and is used. e.g.
.global _main _main: call _main ! strange?? nop
The call instruction will have the following representation:
0x40000000i.e. It will have 01 followed by 30 zero's (as the offset is zero.)
However, stack variables are constrained in two ways: they have limited scope, and limited extent.
Scope and extent. Scope refers to the part of the code in which a variable can be referenced. Extent is the length of time that the variable exists. Scope is an issue that is mainly dealt with at compile-time -- it refers to a program's source code, and in what parts of the source code it is legal to refer to a variable. Extent is an issue that is resolved at run-time -- it refers to the allocation and deallocation of memory as the program runs.
Now, stack variables have both scope and extent limited to an individual subroutine. Stack variables can only be referenced within their subroutine; and stack variables are created and destroyed with their subroutine begins and ends. In order to have other kinds of variables, we need to separate these two characteristics.
Why would we want to modify just scope, or extent, without affecting the other?
Widening scope with limited extent - An example would be languages in which a called subroutine is allowed to use variables declared in the caller. Languages that allow this are some dialects of Lisp, such as Scheme. C doesn't allow this though.
Lengthening extent with limited scope - An example would be, say, a variable that is only accessible within a subroutine, but whose value we wish to preserve across subroutine calls. That is, we want the local variable to have the same value on entry to the subroutine that it had when the subroutine last exited.
The task of widening scope is a job for the compiler and we won't discuss it any more here. However, the task of allowing lengthened extent is a question of memory allocation. We'll discuss the most common form of wider extent that can be provided: to cause the variable to exist for the entire execution of the program. To do this we obviously need a new data structure other than the stack.
The solution is to allocate a portion of memory when the program starts that is used for so-called "static" data. This chunk of memory is called a segment. In fact, the program itself is a chunk of memory that is managed in this way -- it's called the text segment. The memory used for static data is called the data segment.
The reason for using two segments comes from the support that the operating system provides for segments. Later on we'll discuss how the operating system implements segments. For now, we'll note that the OS creates segments when the program starts executing, and it has the ability to make a segment either read-only (R/O) or readable and writeable (R/W). The two segments exist because we typically want our program code to be read/only, while our data must of course be read/write. Making program code (the text segment) R/O is intended to be a help to the programmer, to prevent errors in which program code is accidentally overwritten by an erroneous program. However, it of course means that if a program wants to modify its own code, or generate new code during execution, it must do so in the data segment.