|For more, see:||SPARC at Enchanted Learning|
When an assembly-language program is assembled, the translation that the assembler carries out is essentially the construction of the text segment and the data segment. (The stack grows and shrinks along with function calls and returns during execution, so it doesn't need to be built by the assembler.)
During the time the assembler is reading through and translating an assembly-language program, it always keeps track of where it is currently assembling to: the text segment, the initialized part of the data segment, or the so-called uninitialized (really zero-initialized) part of the data segment.
In your assembly language programs, you are free to intersperse code that generates values for the different segments, switching between segments in any way that's convenient for you. The assembler always keeps track of where it's up to in each segment; if you switch, for example, from the text segment to the initialized part of the data segment and then back to the text segment again, whatever you place in the text segment now will come immediately after whatever you placed in the text segment earlier; the assembler will simply pick up in the text segment where it left off. Why is it useful to switch between segments in your source code? So you can keep code and related data close together in your source.
In order to do this, the assembler maintains three location counters: one each for text, for initialized data, and for uninitialized data. Each location counter refers to an offset from the beginning of the corresponding segment. The three location counters are initialized to 0, since the assembler starts constructing each segment from the beginning of that segment. As the assembler builds each segment, placing values there, it uses the current value of location counter for that segment to determine how many bytes from the beginning of the segment to place each value. The assembler will, of course, increase the location counters as it advances through the segments.
Keep in mind that the location counters are variables of the assembler. (The assembler is a program -- it has variables.) The location counters only have values while the assembler is running, translating your assembly source. It makes no sense to ask about the values of the location counters while your executable program is running, since they're not variables of your program; they only have meaning while the assembler is running.
When the assembler is given a source file to translate, it starts out assembling to the text segment. You can switch which segment is being assembled to by using the following directives:
|.text||Switch to text segment.|
|.data||Switch to initialized part of data segment.|
|.bss||Switch to uninitialized part of data segment.|
".bss" stands for "block starting symbol". After all, the only thing you can do in defining uninitialized data is to give a name to the beginning of a block of data.
Whenever you use one of the directives .text, .data, or .bss, everything assembled after that point is placed by the assembler in the indicated segment, up to the next occurrence of a different one of these three directives.
You need to be careful that you only use each segment for its intended use. The text segment (.text) can contain both code and data (keeping in mind that any data you place in the text segment cannot be changed by your program during execution). The initialized part of the data segment (.data) should contain just data, not code. And the uninitialized part of the data segment (.bss) cannot have values placed in it as assembly time at all -- all you can do here is allocate memory (that is, add to the total amount of memory to be included as uninitialized data). In all three types of segment, you can define symbolic labels; such a label has as its value an address within that segment.
Copyright 1998-1999 Enchanted Learning Software.
|Search the Enchanted Learning website for:|