📄 chapter 4 variables and constants -- valvano.htm
字号:
not lost when characters are stored.</FONT></P>
<P><B><I><FONT face=Helvetica,Arial><A name=WHEN></A>When Do We Use Automatics
Versus Statics?</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">Because their contents are allowed to
change, all variables must be allocated in RAM and not ROM. An <B>automatic
variable</B> contains temporary information used only by one software module. As
we saw, automatic variables are typically allocated, used, then deallocated from
the stack. Since an interrupt will save registers and create its own stack
frame, the use of automatic variables is important for creating reentrant
software. Automatic variables provide protection limiting the scope of access in
such a way that only the program that created the local variable can access it.
The information stored in an automatic variable is not permanent. This means if
we store a value into an automatic variable during one execution of the module,
the next time that module is executed the previous value is not available.
Typically we use automatics for loop counters, temporary sums. We use an
automatic variable to store data that is temporary in nature. In summary,
reasons why we place automatic variables on the stack include</FONT></P>
<DIR>
<P><FONT face="Times New Roman,Times">• dynamic allocation release allows for
reuse of memory<BR>• limited scope of access provides for data protection<BR>•
can be made reentrant.<BR>• limited scope of access provides for data
protection<BR>• since absolute addressing is not used, the code is
relocatable<BR>• the number of variables is only limited by the size of the
stack allocation.</FONT></P></DIR>
<P><FONT face="Times New Roman,Times">A <B>static variable</B> is information
shared by more than one program module. E.g., we use globals to pass data
between the main (or foreground) process and an interrupt (or background)
process. Static variables are not deallocated. The information they store is
permanent. We can use static variables for the time of day, date, user name,
temperature, pointers to shared data. The ICC11/ICC12 compilers use absolute
addressing (direct or extended) to access </FONT>the static variables. </P>
<P><B><I><FONT face=Helvetica,Arial><A name=INITIALIZE></A>Initialization of
variables and constants</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">Most programming languages provide ways of
specifying <I>initial values</I>; that is, the values that variables have when
program execution begins. We saw earlier that the ICC11/ICC12/Hiware compilers
will initially set all static variables to zero. Constants must be initialized
at the time they are declared, and we have the option of initializing the
variables. </FONT></P>
<P><FONT face="Times New Roman,Times">Specifying initial values is simple. In
its declaration, we follow a variable's name with an equal sign and a constant
expression for the desired value. Thus</FONT></P>
<DIR>
<P><CODE>short Temperature = -55;</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">declares </FONT><CODE>Temperature
</CODE><FONT face="Times New Roman,Times">to be a 16-bit signed integer, and
gives it an initial value of -55. Character constants with backslash-escape
sequences are permitted. Thus</FONT></P>
<DIR>
<P><CODE>char Letter = '\t';</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">declares </FONT><CODE>Letter </CODE><FONT
face="Times New Roman,Times">to be a character, and gives it the value of the
tab character.</FONT> <FONT face="Times New Roman,Times">If array elements are
being initialized, a list of constant expressions, separated by commas and
enclosed in braces, is written. For example,</FONT></P>
<DIR>
<P><CODE>const unsigned short Steps[4] = {10, 9, 6, 5};</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">declares </FONT><CODE>Steps </CODE><FONT
face="Times New Roman,Times">to be an unsigned 16-bit constant integer array,
and gives its elements the values 10, 9, 6, and 5 respectively. If the size of
the array is not specified, it is determined by the number of initializers.
Thus</FONT></P>
<DIR>
<P><CODE>char Waveform[] = {28,27,60,30,40,50,60};</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">declares </FONT><CODE>Waveform
</CODE><FONT face="Times New Roman,Times">to be a signed 8-bit array of 7
elements which are initialized to the
</FONT><CODE>28,27,60,30,40,50,60</CODE><FONT face="Times New Roman,Times">. On
the other hand, if the size of the array is given and if it exceeds the number
of initializers, the leading elements are initialized and the trailing elements
default to zero. Therefore,</FONT></P>
<DIR>
<P><CODE>char Waveform[100] = {28,27,60,30,40,50,60};</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">declares </FONT><CODE>Waveform
</CODE><FONT face="Times New Roman,Times">to be an integer array of 100
elements, the first 7 elements of which are initialized to the
</FONT><CODE>28,27,60,30,40,50,60</CODE><FONT face="Times New Roman,Times"> and
the others to zero. Finally, if the size of an array is given and there are too
many initializers, the compiler generates an error message. In that case, the
programmer must be confused.</FONT></P>
<P><FONT face="Times New Roman,Times">Character arrays and character pointers
may be initialized with a character string. In these cases, a terminating zero
is automatically generated. For example,</FONT></P>
<DIR>
<P><CODE>char Name[4] = "Jon";</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">declares </FONT><CODE>Name</CODE><FONT
face="Times New Roman,Times"> to be a character array of four elements with the
first three initialized to 'J', 'o', and 'n' respectively. The fourth element
contains zero. If the size of the array is not given, it will be set to the size
of the string plus one. Thus ca in</FONT></P>
<DIR>
<P><CODE>char Name[] = "Jon";</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">also contains the same four elements. If
the size is given and the string is shorter, trailing elements default to zero.
For example, the array declared by</FONT></P>
<DIR>
<P><CODE>char Name[6] = "Jon";</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">contains zeroes in its last three
elements. If the string is longer than the specified size of the array, the
array size is increased to match. If we write</FONT></P>
<DIR>
<P><CODE>char *NamePt = "Jon";</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">the effect is quite different from
initializing an array. First a word (16 bits) is set aside for the pointer
itself. This pointer is then given the address of the string. Then, beginning
with that byte, the string and its zero terminator are assembled. The result is
that </FONT><CODE>NamePt </CODE><FONT face="Times New Roman,Times">contains the
address of the string "Jon".</FONT> <FONT face="Times New Roman,Times">The
Imagecraft and Hiware compilers accept initializers for character variables,
pointers, and arrays, and for integer variables and arrays. The initializers
themselves may be either constant expressions, lists of constant expressions, or
strings. </FONT></P>
<P><B><I><FONT face=Helvetica,Arial><A name=INITIMPLEMENATION></A>Implementation
of the initialization</FONT></I></B></P>
<P><FONT face="Times New Roman,Times">The compiler initializes static constants
simply by defining its value in ROM. In the following example, J is a static
constant (actually K is a literal)</FONT></P>
<DIR>
<P><CODE>short
I; /* 16
bit global */<BR>const short J=96; /* 16 bit constant
*/<BR>#define K 97;<BR>void main(void){
<BR> I=J; <BR> I=K;}</CODE></P></DIR>
<ADDRESS>Listing 4-14: An example showing the initialization of a static
constant</ADDRESS>
<P> </P>
<P><FONT face="Times New Roman,Times">The 6811 code generated by the ICC11
Version 4 compiler is as follows</FONT></P>
<DIR>
<P><CODE> .area text <BR> .global
_main<BR>_main: <BR> ldd
_J<BR> std _I ;16
bits<BR> ldd #97<BR> std
_I ;16 bits<BR> rts
<BR> .area bss<BR> .global
_I<BR>_I: .blkb 2 <BR> .area text
<BR> .global _J<BR>_J: .word 96</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">The 6812 code generated by the ICC12
Version 5.1 compiler is as follows</FONT></P>
<DIR>
<P><CODE> .area text <BR>_main::
<BR> pshx <BR> tfr s,x
<BR> movw _J,_I ;16
bits<BR> movw #97,_I ;16 bits
<BR> tfr x,s <BR> pulx
<BR> rts <BR> .area bss<BR>_I::
.blkb 2 <BR> .area text <BR>_J:: .word
96</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">Notice the use of the <B>#define</B> macro
implements an operation similar to the literal </FONT><FONT
face=Monaco>I=97;</FONT></P>
<P><FONT face="Times New Roman,Times">The compiler initializes static variables
simply by defining its initial value in ROM. It creates another segment called
<I>idata</I> (in addition to the <I>data</I> and <I>text</I> sections). It
places the initial values in the <I>idata</I> segment, then copies the data
dynamically from <I>idata</I> ROM information into <I>data</I> RAM variables at
the start of the program (before main is started). (How ICC11 and ICC12 have
handled initialized variables has changed over the various release versions. The
particular compiler version you are using may handle this process differently.)
For example</FONT></P>
<DIR>
<P><CODE>short I=95; /* 16
bit global */<BR>void main(void){
<BR> <BR> }</CODE></P></DIR>
<P><FONT face="Times New Roman,Times">The ICC11 Version 4 code would not
function properly on an embedded system because the global is defined
as</FONT></P>
<P><CODE> .area bss<BR>_I:: .word 95</CODE></P>
<P><FONT face="Times New Roman,Times">The ICC11 Version 4 code would work on a
RAM based system like the Motorola 6811 EVB where the power is not removed
between the time the S19 record is loaded into RAM and the time the software is
executed. Proper 6812 code is generated by the ICC12 compiler. In the 6812
solution, code in the <B>CRT12.S</B> file will copy the 95 from <B>.idata</B>
(ROM) into <B>_I</B> in <B>bss</B> (RAM) upon a hardware reset. This copy is
performed transparently before the main program is started.</FONT></P>
<DIR>
<P><CODE> .area text <BR>_main::
<BR> pshx <BR> tfr
s,x<BR><BR> pulx <BR> rts
<BR> .area bss<BR>_I:: .blkb 2
<BR> .area idata <BR> .word
95</CODE></P>
<P> </P></DIR>
<P><FONT face="Times New Roman,Times">Even though the following two applications
of global variable are technically proper, the explicit initialization of global
variables in my opinion is a better style.</FONT></P>
<DIR>
<P><CODE>/* poor style */ /* good style
*/<BR>int
I=95; int
I;<BR>void main(void){ void main(void){
<BR> I=95;<BR>} }</CODE></P></DIR>
<ADDRESS>Opinion: I firmly believe a good understanding of the assembly code
generated by our compiler makes us better programmers.</ADDRESS>
<P><FONT face="Times New Roman,Times">Go to <A
href="http://www.ece.utexas.edu/~valvano/embed/chap5/chap5.htm">Chapter 5 on
Expressions</A> Return to <A
href="http://www.ece.utexas.edu/~valvano/embed/toc1.htm">Table of Contents</A>
</FONT></P></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -